演员之间的事件

时间:2014-02-11 08:21:40

标签: java events libgdx actor

我正在尝试使用事件对演员做些什么,但我不明白如何正确地做到这一点。

我的屏幕上有一个按钮和一个文本(例如)。他们都是舞台上的演员 我的目的是:如果我点击按钮,我想改变文字

我在我的按钮上添加了监听器,我得到了点击,但我不知道如何将事件(或其他任何内容)发送到我的文本来设置它。

主要课程有阶段定义和他的

public class AGame implements ApplicationListener {
private WorldRendererTouchPad renderer;
private Stage stage;
private static Vector3 cameraVelocity=new Vector3(0,0,0);

private ButtonJump button;

public static final int SCREEN_WIDTH=800;
public static final int SCREEN_HEIGHT=480;

public void create() {
    stage = new Stage();
    stage.setViewport(SCREEN_WIDTH, SCREEN_HEIGHT, true);
    stage.getCamera().translate(-stage.getGutterWidth(), -stage.getGutterHeight(), 0);

    renderer = new MyRenderer(SCREEN_WIDTH, SCREEN_HEIGHT);
    stage.addActor(renderer);       
    renderer.create();

    button=new ButtonJump();
    stage.addActor(button);     
    button.create();

    Gdx.input.setInputProcessor(stage);
}
....
resize and other methods 
}

MyRenderer类(包含文本actor):

public class MyRenderer  {
private TextTest text;

public MyRenderer(float screenWidth, float screenHeight) {
    setBounds(0, 0, screenWidth, screenHeight);
}

public void create() {
    this.initActors();      
}

private void initActors() {
    text=new TextTest("Hello world!");
    addActor(text);
}


// is it usefull?
public void setText(String newText) {
    text.setText(newText);

}

}

和ButtonJump类(仅在此处扩展MyButton以定义Skin和ButtonStyle)

public class ButtonJump extends MyButton {
public boolean isJump=false;

private static InputListener buttonListener=new InputListener() {
    public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
        Gdx.app.log("event" , "="+event.toString());

        // do something to update text

        return true;
    }
};


public ButtonJump() {
    super();
}

public void create() {
    this.setPosition(getStage().getWidth()-60, 30);
    this.addCaptureListener(buttonListener);
}

public void capture() {
    if (this.isJump)
        Gdx.app.log("jump button", "Jump is set");
    else
        Gdx.app.log("jump button", "No jump");

}
}

1 个答案:

答案 0 :(得分:0)

如果使用clicklistener,则需要让另一个actor保持对它的引用,以便在单击时调用方法。让所有演员互相了解并不是一件好事。使用匿名方式。

游戏中有一个“常用”系统。

如果您确实想使用事件,请实施事件系统。因此,您有一个接口Listen和一个接口Event_Handler。在游戏开始时,您启动一​​个Eventhandler的实现。界面至少应如下所示:

public interface Interface_EventHandler extends Disposable
{
    public void handleEvent(final Event... e);
    public void registerListener(final Interface_Listen listener,
            final Event_Type... type);
    public void unregisterListener(final Interface_Listen... listener);
    public void unregisterAllListener();
    public void unregisterAllListener(final Event_Type... type);
    public void processEvents();
    public void processEvents(final int maxTimeInMS);
}

好的,现在它是如何运作的。处理程序有一个hashmap,其中所有事件类型为Key,侦听器列表为Value。因此,如果有人想要注意一个事件,他会在权限registerListerner(Enum)的处理程序中向Event_Type注册。它需要具有接口侦听获取事件。现在,每个人都可以使用handleEvent(...)方法将事件推送到处理程序中。甚至不止一个..(varargs)..

好的,仍然没有解释它是如何工作的。我们现在有一个注册的监听器(例如actor),我们有进入处理程序的事件。

每个Rendercycle都会在hanlder上调用processEvents()一次。这意味着在帧中推入的每个事件都会在下一帧处理。 (Asynchronus)虽然他迭代所有事件并将它们推送给听众。此外,监听器也应该有一个队列,他们放置所有事件,当他们在.act()他们处理事件时。 (更多asynchronus)。

好的,这是我使用的Handler:

package com.portaaenigma.eventsystem;

import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import com.badlogic.gdx.utils.TimeUtils; import com.portaaenigma.managers.Logger;

public class EventHandler实现Interface_EventHandler {     private HashMap>听众;     私人LinkedList事件;

public EventHandler()
{
    listeners = new HashMap<Event_Type, ArrayList<Interface_Listen>>();
    // add the arraylist for every Eventtype
    for (Event_Type e : Event_Type.values())
    {
        listeners.put(e, new ArrayList<Interface_Listen>());
    }
    events = new LinkedList<Event>();
}

@Override
public void handleEvent(final Event... e)
{
    for (Event event : e)
    {
        events.push(event);
    }
}

@Override
public void unregisterListener(final Interface_Listen... listener)
{
    for (Event_Type e : Event_Type.values())
    {
        for (Interface_Listen interface_Listen : listener)
        {
            listeners.get(e).remove(interface_Listen);
        }
    }
}

@Override
public void processEvents()
{
    while (events.size() != 0)
    {
        // get the first element and delete it
        Event e = events.pop();
        for (Interface_Listen l : listeners.get(e.getType()))
        {
            l.handleEvent(e);
        }
    }
}

@Override
public void processEvents(final int maxTimeInMS)
{
    int startSize = 0;
    if (events.size() != 0)
    {
        startSize = events.size();
        Logger.log("Processing Events: " + events.size());
    }
    long startTime = TimeUtils.millis();

    while (events.size() != 0)
    {
        // get the first element and delete it
        Event e = events.pop();
        for (Interface_Listen l : listeners.get(e.getType()))
        {
            l.handleEvent(e);
        }
        // stop handling if time is up
        if (startTime - TimeUtils.millis() > maxTimeInMS)
        {
            Logger.log("Handled " + (events.size() - startSize) + " Events");
            break;
        }
    }
}

@Override
public void registerListener(final Interface_Listen listener,
        Event_Type... type)
{
    for (Event_Type event_Type : type)
    {
        listeners.get(event_Type).add(listener);
    }
}

@Override
public void unregisterAllListener()
{
    Logger.log("UnregisterAll");
    for (Event_Type e : Event_Type.values())
    {
        listeners.get(e).clear();
    }
}

@Override
public void unregisterAllListener(final Event_Type... type)
{
    for (Event_Type event_Type : type)
    {
        listeners.get(event_Type).clear();
    }
}

@Override
public void dispose()
{
    unregisterAllListener();
    events.clear();
    listeners.clear();
}
}

所有听众的界面都很简单就是这样: 公共接口Interface_Listen

{
    public void handleEvent(final Event e);
}

最后但并非最不重要的事件。你现在怎么发送不同的数据?安静简单。从字符串和字符串中获取一个hashmap,并确保使用EventType。

public class Event
{
private Event_Type type;
private HashMap<String, String> m_messages;

public Event(final Event_Type e, final Event_Message... m)
{
    m_messages = new HashMap<String, String>();
    for (Event_Message message : m)
    {
        m_messages.put(message.m_key, message.m_value);
    }
    type = e;
}


public Event_Type getType()
{
    return type;
}

public void addMessages(final Event_Message... m)
{
    for (Event_Message event_Message : m)
    {
        m_messages.put(event_Message.m_key, event_Message.m_value);
    }
}

public String getMessage(final String name)
{
    if (m_messages.get(name) == null)
    {
        Logger.error("Message not found: " + name);
    }

    // if null return an empty string
    return m_messages.get(name) != null ? m_messages.get(name) : "";
}

public void clearMessages()
{
    m_messages.clear();
}
}

好的,我希望这能解释如何在游戏中实现EventSystem。这种高度不是其他软件的常规方式,但在游戏中,您可以将事件排队并在Gameloop循环中处理它们一次。听众也这样做。

所以在你的情况下。实现这样的处理程序并将actor注册为侦听器。当然,他们需要实现侦听器接口并对事件执行某些操作。让一个演员将事件推送到处理程序中,该处理程序指向另一个演员并完成。 他们的活动不需要彼此了解,而且它确实适用于和你一样多的演员。您甚至可以为不同类别的不同演员创建1个事件,依此类推。例如在mapchange中有用。你通过通知推送一个事件。“changemap”..并且每个演员都知道他需要停止移动,并且每个子系统都知道它确实需要停止因为mapchange等等...

它似乎有点矫枉过正,但它有很多优点,即使在早期阶段也很有用。我做了一些错误,后来开始使用它,现在我后悔了。

抱歉。这不是常规的java标准,但我认为更清楚......对于很多类似的varargs抱歉。可能会让人感到困惑。


Literatur:

Game Coding Complete, Fourth Edition第11章