背景
在我的应用程序(游戏)中 - 我有一个场景管理器来处理不同级别。所以我有:
接口代码
//Interface to allow switching scenes (works in conjunction with SceneManager class)
//Handles rendering, logic updating (on the GL rendering thread) and user input (on the main UI thread)
public interface Scene {
void render();
void updateLogic();
boolean onTouchEvent(MotionEvent event);
}
SceneManager类
//Scene Manager class used in conjunction with the Scene interface. This allows for querying of the current
//scene & changing the scene using the current instance of the manager.
public class SceneManager {
private static SceneManager Instance = new SceneManager();
private Scene currentScene;
public static SceneManager getInstance(){
return Instance;
}
public Scene getCurrentScene(){
return currentScene;
}
public void setCurrentScene(Scene scene){
currentScene = scene;
}
}
所以,从我的游戏循环中我可以做到这样的事情:
SceneManager.getInstance().getCurrentScene().updateLogic();
SceneManager.getInstance().getCurrentScene().render();
我可以通过保存一个简单的int值并通过switch语句运行相应的代码来轻松更改我的级别。
switch (level){
case 1:{SceneManager.getInstance().setCurrentScene(r.level1);break
}
问题
这很好但是在我的一些级别(20个中的2个)中我需要运行一个特定的方法,但我不想在18个级别中实现它,在这个级别中它不是必需的(通过存根方法)。
我的另一个选择是在循环运行时在级别值上调用switch语句....
伪代码
If (level==5)
callCode(5,0);
else if (level==10)
{callCode (10,4);}
(等级5和10是需要这段代码的等级)
....但我宁愿把所需的方法放在它的相应级别类中,只是从当前场景中调用方法,因为我不确定在游戏循环中使用开关(或方法)本身正在运行 - (IE,我的大部分开关语句都来自于一个级别结束时的切割场景,而性能不是真正的问题)。像这样:
我更愿意做这样的事情:
SceneManager.getInstance().getCurrentScene().callCode();
其中callCode方法特定于级别中需要的任何值(或者实际上,然后可以简单地调用公共代码的主方法,但具有不同的值)。
希望我有意义。
任何指针都将不胜感激
修改
尝试创建第二个界面:
public interface Scene2 extends Scene {
void callCode();
}
(场景仍然如上所述)
然后,在我的班级(例如说level10)
public class Level10 implements Scene2 {
@Override
public void render(){
//Rendering code goes here
mainGame.Drawsprites(); //As an example. MainGame implements Scene and contains all my game code. I can simply call the various methods from any of my level classes therefore I don't duplicate tons of code
}
@Override
public void updateLogic(){
//Game updates goes here (Similar to above)
}
@Override
public void callCode(){
//Level specific code here
}
来自我的mainGame课程:
public void doSomething(){
SceneManager.getInstance().getCurrentScene().callCode;
}
}
答案 0 :(得分:0)
如果您有界面Scene
:
public interface Scene {
void render();
void updateLogic();
boolean onTouchEvent(MotionEvent event);
}
您可以定义另一个界面,例如:
public interface Scene2 extends Scene {
void callCode();
}
然后在你的mainGame课中你可以做到:
public void doSomething(){
Object currentScene = SceneManager.getInstance().getCurrentScene();
if(currentScene instanceof Scene){
((Scene)currentScene).render();
((Scene)currentScene).updateLogic();
}
if(currentScene instanceof Scene2){
((Scene2)currentScene).allCode();
}
}
答案 1 :(得分:0)
您应该定义一个扩展您的界面的额外图层。然后,您的2个独立场景可以实现此接口,并且仍然可以通过更通用的界面进行调用。
这是一个示例实现:
public class Main {
public static void main(String[] args) {
SomeInterface obj1 = new SomeClass2();
obj1.method1();
obj1.method2();
SomeSubInterface obj2 = new SomeClass2();
obj2.method1();
obj2.method2();
obj2.method3();
}
}
interface SomeInterface {
void method1();
void method2();
}
interface SomeSubInterface extends SomeInterface {
void method3();
}
class SomeClass1 implements SomeInterface {
@Override
public void method1() {
// TODO Auto-generated method stub
}
@Override
public void method2() {
// TODO Auto-generated method stub
}
}
class SomeClass2 implements SomeSubInterface {
@Override
public void method1() {
// TODO Auto-generated method stub
}
@Override
public void method2() {
// TODO Auto-generated method stub
}
@Override
public void method3() {
// TODO Auto-generated method stub
}
}
答案 2 :(得分:0)
仅举例说明我在上述评论中提出的解决方案。如上所述,它实现了对场景特定代码的本地化,并消除了一般游戏循环的复杂性。
public class Main {
public static void main(String[] args) {
Scene scene1 = new NormalScene();
Scene scene2 = new SpecialScene();
scene1.initialize(); //Does nothing
scene2.initialize(); //Print hello world
}
}
abstract class Scene {
abstract void render();
abstract void updateLogic();
abstract boolean onTouchEvent();
void initialize() {
}
}
class NormalScene extends Scene {
@Override
void render() {
}
@Override
void updateLogic() {
}
@Override
boolean onTouchEvent() {
return true;
}
}
class SpecialScene extends Scene {
@Override
void render() {
}
@Override
void updateLogic() {
}
@Override
boolean onTouchEvent() {
return true;
}
@Override
void initialize() {
System.out.println("Hello world");
}
}
答案 3 :(得分:0)
正如我的评论中所述,我会喜欢以下方法,因为它非常适合Android的设计并为您提供最大的灵活性:
public interface Scene {
void render();
void updateLogic();
boolean onTouchEvent(MotionEvent event);
/** additional lifecycle callbacks **/
void onBeforeRender();
void onAfterRender();
void onBeforeUpdateLogic();
void onAfterUpdateLogic();
/** though the naming updateLogic associated that it is not a typicall lifecycle related method **/
}
在您的课程中,当然还有事件监视器的setter和getter附加到生命周期事件。
答案 4 :(得分:0)
根据您的评论从其他答案中提取:我认为您最想尽量减少Scene
界面的做法是将visitor pattern添加到您的代码中(它是一个双重调度设计模式)。基本上对你而言,这意味着(我假设第2级和第4级是你想要调用特殊方法的级别类):
interface LevelVisitor {
void visit(Level2 level);
void visit(Level4 level);
}
interface Scene {
// Other methods stay the same as you have
accept(LevelVisitor visitor);
}
您的不同级别现在有accept
方法(在18/20课程中不需要它的课程中将其留空),上面我使LevelVisitor
收到具体的{{1}您的class
和Level2
类(两个特定级别)的实现。
让Level4
类实现MainGame
接口,这意味着MainGame类中现在有两个新方法,即接收具体LevelVisitor
和Level2
类实现的方法。所以现在从Level4
拨打电话(MainGame
会被调度到需要它的级别,MainGame/this
是访问者):
MainGame
并且您在SceneManager.getInstance().getCurrentScene().accept(this);
MainGame
在public void visit(Level2 level) {
level.specificMethodInLevel2();
}
public void visit(Level4 level) {
level.specificMethodInLevel4();
}
和Level2
类中,您使用非空实现的accept方法,例如Level4
中的Level2
Level2/this
将调度MainGame
}}):
public void accept(LevelVisitor visitor) {
visitor.visit(this);
}
现在您可以将特定方法(例如specificMethodInLevel2()
)添加到Level2
和Level4
具体类中,这些类别是从其他级别看不到的,并从访问中调用它们你MainGame
班的方法。此外,由于访问者模式的调度性质,您最终没有切换案例(所有“特殊”级别现在都采用不同的方法处理)。