如何添加国家我的游戏? [英] How can I add States to my game?

查看:158
本文介绍了如何添加国家我的游戏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我目前的游戏中有都应该是不同的状态,例如,当我在游戏的主菜单,状态会变成MainMenu的,如果我在游戏(游戏GAME)国家将是游戏。

由于它是现在只是开始这款游戏,而不是MainMenu的。所以我的问题是我如何添加它,这样它工作的方式应该?

编辑:我希望游戏中当然的MainMenu态启动,在不清楚:),然后preSS玩来开始游戏游戏的情况下,退出,退出或者选择等。

编辑2:第一个code的非工作Statefunction。底部的code具有Statefunction,做的工作。为什么我不能似乎使它成为第一个code工作?

code:

 包Game.Window;进口java.awt.Canvas中;
进口java.awt.Color中;
进口java.awt.Graphics;
进口java.awt.Graphics2D中;
进口java.awt.image.BufferStrategy;
进口java.awt.image.BufferedImage中;
进口了java.util.Random;进口Game.Framework.AudioPlayer;
进口Game.Framework.KeyInput;
进口Game.Framework.ObjectId;
进口Game.Framework.Texture;
进口Game.Interfaces.MainMenu;
进口Game.Objects.Block;
进口Game.Objects.Player;公共类游戏扩展画布实现Runnable {
    私有静态最后的serialVersionUID长= -3258890003398871268L;    私人布尔运行= FALSE;
    私人螺纹螺纹;    公共静态INT宽度,高度;    //缓冲区级别和背景
    私人的BufferedImage级别= NULL,背景= NULL;    处理程序处理程序;
    摄像头凸轮;
    静态纹理TEX;    随机兰特=新的随机();    公共枚举状态{
        主菜单,
        游戏,
    };    公共静态游戏状态= STATE.MainMenu;    公共无效的init(){
        WIDTH =的getWidth();
        HEIGHT =的getHeight();        AudioPlayer.load();
        AudioPlayer.getMusic(音乐),循环()。        TEX =新的纹理();        BufferedImageLoader装载机=新BufferedImageLoader();
        等级= loader.loadImage(/ Level.png); //加载图像级别
        背景= loader.loadImage(/ BackGround.png); //加载图像背景        处理器=新的处理程序();        凸轮=新照相机(0,0);        LoadImageLevel(级别);        this.addKeyListener(新KeyInput(处理器,NULL));
    }
    公共同步启动无效(){
        如果(运行)
            返回;
        运行= TRUE;
        线程=新主题(本);
        thread.start();
    }
    //该Game_Loop
    公共无效的run(){
        在里面();
        this.requestFocus();
        长lastTime = System.nanoTime();
        双amountOfTicks = 60.0;
        双NS = 10亿/ amountOfTicks;
        双Δ= 0;
        长定时器= System.currentTimeMillis的();
        INT更新= 0;
        INT帧= 0;        而(运行){
            长今= System.nanoTime();
            三角洲+ =(现 - lastTime)/ NS;
            lastTime =现在;            而(增量> = 1){
                蜱();
                更新++;
                三角洲 - ;
            }
            渲染();
            帧++;            如果(System.currentTimeMillis的() - 定时器> 1000){
                计时器+ = 1000;
                的System.out.println(FPS:+帧+ - TICKS:+更新);
                帧= 0;
                更新= 0;
            }
        }
    }
    私人无效打勾(){
        如果(Game.gameState == STATE.Game){
            handler.tick();
        }否则如果(Game.gameState == STATE.MainMenu){
            //MainMenu.tick();
        }        的for(int i = 0; I< handler.object.size();我++){
            如果(handler.object.get(ⅰ).getId()== ObjectId.Player){
                cam.tick(handler.object.get(I));
            }
        }
    }
    私人无效渲染(){
        BufferStrategy中BS = this.getBufferStrategy();
        如果(BS == NULL){
            this.createBufferStrategy(3);
            返回;
        }        图形G = bs.getDrawGraphics();
        Graphics2D的G2D =(Graphics2D的)克;
        // 的背景
        g.setColor(新彩(25,191,224));
        g.fillRect(0,0,的getWidth(),的getHeight());        //摄像机的开头
        g2d.translate(cam.getX(),cam.getY());            为(中间体XX = 0; XX&下; Background.getWidth()* 10; XX + = Background.getWidth())
                g.drawImage(背景,XX,50,本);
            handler.render(G);        g2d.translate(-cam.getX(),-cam.getY());
        //摄像机的结束
        g.dispose();
        bs.show();
    }
    私人无效LoadImageLevel(BufferedImage的图像){
        INT W = image.getWidth();
        INT H = image.getHeight();        的System.out.println(宽度,高度:+ W ++ H);        为(中间体XX = 0; XX&下; H; XX ++){
            对于(INT YY = 0; YY< H; YY ++){
                INT像素= image.getRGB(XX,YY);
                INT红色=(象素>> 16)及0xFF的;
                INT绿色=(像素>> 8)及0xFF的;
                INT蓝色=(像素)及0xFF的;                如果(红色== 255安培;&安培;绿色== 255安培;和蓝光== 255)handler.addObject(新块(XX * 32,YY * 32,0,ObjectId.Block));
                如果(红色== 0安培;&安培;绿色== 255安培;和蓝光== 0)handler.addObject(新块(XX * 32,YY * 32,1,ObjectId.Block));
                如果(红色== 0安培;&安培;绿色== 38安培;和蓝光== 255)handler.addObject(新播放器(XX * 32,YY * 32,处理器,ObjectId.Player));
            }
        }
    }
    公共静态纹理的getInstance(){
        返回TEX;
    }
}

在MainMenu的:

 包Game.Interfaces;进口java.awt.Color中;
进口java.awt.Font中;
进口java.awt.Graphics;
进口java.awt.event.MouseAdapter;
进口java.awt.event.MouseEvent中;进口Game.Framework.AudioPlayer;
进口Game.Window.Game;
进口Game.Window.Game.STATE;
进口Game.Window.Handler;公共类MainMenu的扩展MouseAdapter {    私人游戏游戏;
    私人处理程序处理程序;    公众的MainMenu(Game游戏,处理程序处理){
        this.game =游戏;
        this.handler =处理程序;
    }    公共无效鼠标pressed(的MouseEvent E){
        INT MX = e.getX();
        诠释我= e.getY();        如果(Game.gameState == STATE.MainMenu){
            如果(鼠标悬停(MX,MY,10,10,50,50)){
                AudioPlayer.getSound(menu_sound)打()。
                Game.gameState = STATE.Game;
                返回;
            }
        }
    }
    公共无效的mouseReleased(的MouseEvent E){
    }
    私人布尔鼠标悬停(INT MX,我的诠释,诠释的x,INT Y,INT宽度,高度INT){
        如果(MX> X&放大器;&功放; MX< X + WIDTH){
            如果(我的> Y&放大器;&安培;我< Y +高){
                返回true;
            }否则返回false;
        }否则返回false;
    }
    公共无效打勾(){
    }
    公共无效渲染(图形G){
        如果(Game.gameState == STATE.MainMenu){
            字体FNT1 =新的字体(宋体,1,50);            g.setFont(FNT1);
            g.setColor(Color.WHITE);
            g.drawRect(10,10,100,100);
            g.drawString(主菜单,10,10);
        }
    }
}

在蜱和渲染我知道我需要打勾并呈现只有特定状态的方法,所以如果我是在MainMenu的那只蜱和渲染。

这些国家的作品在本场比赛:

 包游戏;进口java.awt.Canvas中;
进口java.awt.Color中;
进口java.awt.Graphics;
进口java.awt.image.BufferStrategy;
进口了java.util.Random;公共类游戏扩展画布实现Runnable {    私有静态最后的serialVersionUID长= 7364682855700581664L;    公共静态最终诠释WIDTH = 800 HEIGHT = WIDTH / 12 * 9;    私人螺纹螺纹;
    私人布尔运行= FALSE;    公共静态布尔暂停= FALSE;
    公众诠释差异= 0;    // 0 = EASY
    // 1 = NORMAL
    // 2 =硬    私人随机ř;
    私人处理程序处理程序;
    私人HUD平视显示器;
    私人产卵产卵;
    私人菜单菜单;    公共枚举状态{
        菜单,
        选项
        游戏,
        选择,
        失去
    };    公共静态游戏状态= STATE.Menu;    公共游戏(){
        HUD =新的HUD();
        处理器=新的处理程序();
        菜单=新的菜单(这一点,处理程序,HUD);
        this.addKeyListener(新KeyInput(处理器,这一点));
        this.addMouseListener(菜单);        AudioPlayer.load();
        AudioPlayer.getMusic(音乐),循环()。        新的窗口(宽度,高度,测试赛,本);        产卵=新的产卵(处理器,HUD,这一点);
        R =新的随机();        如果(游戏状态== STATE.Game){
            handler.addObject(新播放器(宽/ 2-32,身高/ 2-32,ID.Player,处理程序));
            handler.addObject(新BasicEnemy(r.nextInt(Game.WIDTH - 50),r.nextInt(Game.HEIGHT - 50),ID.BasicEnemy,处理程序));
        }
    }    公共同步启动无效(){
        线程=新主题(本);
        thread.start();
        运行= TRUE;
    }    公共同步无效停止(){
        尝试{
            的Thread.join();
            运行= FALSE;
        }赶上(例外五){
            e.printStackTrace();
        }
    }    公共无效的run(){
        this.requestFocus();
        长lastTime = System.nanoTime();
        双amountOfTicks = 60.0;
        双NS = 10亿/ amountOfTicks;
        双Δ= 0;
        长定时器= System.currentTimeMillis的();
        INT帧= 0;
        而(运行){
            长今= System.nanoTime();
            三角洲+ =(现 - lastTime)/ NS;
            lastTime =现在;
            而(增量> = 1){
                蜱();
                三角洲 - ;
            }
            如果(运行)
                渲染();
            帧++;            如果(System.currentTimeMillis的() - 定时器> 1000){
                计时器+ = 1000;
                的System.out.println(FPS:+帧);
                帧= 0;
            }
        }
        停止();
    }    私人无效打勾(){
        如果(游戏状态== STATE.Game){
            如果(!暂停){
                hud.tick();
                spawner.tick();
                handler.tick();                如果(HUD.PlayerHealth&所述; 1){
                    HUD.PlayerHealth = 100;
                    //hud.setLevel(1);
                    //hud.setScore(0);
                    游戏状态= STATE.Lose;
                    handler.clearEnemies();
                }
            }        }否则如果(游戏状态== STATE.Menu ||游戏状态== || STATE.Lose游戏状态== STATE.Select){
            menu.tick();
            handler.tick();
        }
    }    私人无效渲染(){
        BufferStrategy中BS = this.getBufferStrategy();
        如果(BS == NULL){
            this.createBufferStrategy(3);
            返回;
        }        图形G = bs.getDrawGraphics();        g.setColor(Color.BLACK);
        g.fillRect(0,0,宽度,高度);        handler.render(G);        如果(暂停){
            g.setColor(Color.RED);
            g.drawString(暂停,370,260);
        }        如果(游戏状态== STATE.Game){
            hud.render(G);
        }否则如果(游戏状态== STATE.Menu ||游戏状态== || STATE.Options游戏状态== || STATE.Lose游戏状态== STATE.Select){
            menu.render(G);
    }        g.dispose();
        bs.show();
    }    公共静态浮动钳(VAR浮动,浮动最小,最大浮动){
        如果(VAR> =最大值)
            返回VAR = MAX;
        否则,如果(VAR< =分钟)
            返回VAR =分钟;
        其他
            返回VAR;
    }    公共静态无效的主要(字符串ARGS []){
        新游戏();
    }
}


解决方案

您可以用两种不同的方式重新设计的游戏。

选项1:

有限状态机以pre-定义工作流程:推荐,如果你知道你的游戏的所有状态提前和状态机几乎是固定的,而不在未来的变化

选项2:

行为树木:推荐,如果有频繁变更的博弈行为。您可以动态地添加行为,以现有的树,而不会影响当前行为。

请参考下面的相关问题,SE的更多详细信息。

<一个href=\"http://stackoverflow.com/questions/13221168/how-to-implement-a-fsm-finite-state-machine-in-java/36355828#36355828\">How实施FSM - 有限状态机在Java中

In my current game there are supposed to be different states, for example when I am in the Main Menu of the game, the state would turn "MainMenu", if I am in the game (The game GAME) the state would be "Game".

As it is right now it just starts the game GAME and not the MainMenu. So my question is how can I add it so that it works the way it should?

EDIT: I want the game to start in the MainMenu-STATE of course, in case that wasn't clear :) And then press "play" to start the Game GAME, "Exit" to exit or "options" and so on.

EDIT 2: The first code has the non-working Statefunction. The code at the bottom has a Statefunction that does work. Why can't I seem to make it work for the first code?

Code:

package Game.Window;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.util.Random;

import Game.Framework.AudioPlayer;
import Game.Framework.KeyInput;
import Game.Framework.ObjectId;
import Game.Framework.Texture;
import Game.Interfaces.MainMenu;
import Game.Objects.Block;
import Game.Objects.Player;

public class Game extends Canvas implements Runnable{
    private static final long serialVersionUID = -3258890003398871268L;

    private boolean running = false;
    private Thread thread;

    public static int WIDTH, HEIGHT;

    // Buffers the "Level" and "Background"
    private BufferedImage Level = null, Background = null;

    Handler handler;
    Camera cam;
    static Texture tex;

    Random rand = new Random();

    public enum STATE{
        MainMenu,
        Game,
    };

    public static STATE gameState = STATE.MainMenu;

    public void init(){
        WIDTH = getWidth();
        HEIGHT = getHeight();

        AudioPlayer.load();
        AudioPlayer.getMusic("music").loop();

        tex = new Texture();

        BufferedImageLoader loader = new BufferedImageLoader();
        Level = loader.loadImage("/Level.png"); // Loads the image "Level"
        Background = loader.loadImage("/BackGround.png"); // Loads the image "Background"

        handler = new Handler();

        cam = new Camera(0, 0);

        LoadImageLevel(Level);

        this.addKeyListener(new KeyInput(handler, null));
    }
    public synchronized void start(){
        if(running)
            return;
        running = true;
        thread = new Thread(this);
        thread.start();
    }
    // The Game_Loop
    public void run(){
        init();
        this.requestFocus();
        long lastTime = System.nanoTime();
        double amountOfTicks = 60.0;
        double ns = 1000000000 / amountOfTicks;
        double delta = 0;
        long timer = System.currentTimeMillis();
        int updates = 0;
        int frames = 0;

        while(running){
            long now = System.nanoTime();
            delta += (now - lastTime) / ns;
            lastTime = now;

            while(delta >= 1){
                tick();
                updates++;
                delta--;
            }
            render();
            frames++;

            if(System.currentTimeMillis() - timer > 1000){
                timer += 1000;
                System.out.println("FPS: " + frames + " - TICKS: " + updates);
                frames = 0;
                updates = 0;
            }
        }
    }
    private void tick(){
        if(Game.gameState == STATE.Game){
            handler.tick();
        }else if(Game.gameState == STATE.MainMenu){
            //MainMenu.tick();
        }

        for(int i = 0; i < handler.object.size(); i++){
            if(handler.object.get(i).getId() == ObjectId.Player){
                cam.tick(handler.object.get(i));
            }
        }
    }
    private void render(){
        BufferStrategy bs = this.getBufferStrategy();
        if(bs == null){
            this.createBufferStrategy(3);
            return;
        }

        Graphics g = bs.getDrawGraphics();
        Graphics2D g2d = (Graphics2D) g;
        // The background
        g.setColor(new Color(25, 191, 224));
        g.fillRect(0, 0, getWidth(), getHeight());

        // Beginning of the Camera
        g2d.translate(cam.getX(), cam.getY());

            for(int xx = 0; xx < Background.getWidth() * 10; xx += Background.getWidth())
                g.drawImage(Background, xx, 50, this);
            handler.render(g);

        g2d.translate(-cam.getX(), -cam.getY());
        // Ending of the Camera
        g.dispose();
        bs.show();
    }
    private void LoadImageLevel(BufferedImage image){
        int w = image.getWidth();
        int h = image.getHeight();

        System.out.println("Width, Height: " + w + " " + h);

        for(int xx = 0; xx < h; xx++){
            for(int yy = 0; yy < h; yy++){
                int pixel = image.getRGB(xx, yy);
                int red = (pixel >> 16) & 0xff;
                int green = (pixel >> 8) & 0xff;
                int blue = (pixel) & 0xff;

                if(red == 255 && green == 255 && blue == 255) handler.addObject(new Block(xx*32, yy*32, 0, ObjectId.Block));
                if(red == 0 && green == 255 && blue == 0) handler.addObject(new Block(xx*32, yy*32, 1, ObjectId.Block));
                if(red == 0 && green == 38 && blue == 255) handler.addObject(new Player(xx*32, yy*32, handler, ObjectId.Player));
            }
        }
    }
    public static Texture getInstance(){
        return tex;
    }
}

The MainMenu:

package Game.Interfaces;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import Game.Framework.AudioPlayer;
import Game.Window.Game;
import Game.Window.Game.STATE;
import Game.Window.Handler;

public class MainMenu extends MouseAdapter{

    private Game game;
    private Handler handler;

    public MainMenu(Game game, Handler handler){
        this.game = game;
        this.handler = handler;
    }

    public void mousePressed(MouseEvent e){
        int mx = e.getX();
        int my = e.getY();

        if(Game.gameState == STATE.MainMenu){
            if(mouseOver(mx, my, 10, 10, 50, 50)){
                AudioPlayer.getSound("menu_sound").play();
                Game.gameState = STATE.Game;
                return;
            }
        }
    }
    public void mouseReleased(MouseEvent e){
    }
    private boolean mouseOver(int mx, int my, int x, int y, int WIDTH, int HEIGHT){
        if(mx > x && mx < x + WIDTH){
            if(my > y && my < y + HEIGHT){
                return true;
            }else return false;
        }else return false;
    }
    public void tick(){
    }
    public void render(Graphics g){
        if(Game.gameState == STATE.MainMenu){
            Font fnt1 = new Font("Arial", 1, 50);

            g.setFont(fnt1);
            g.setColor(Color.WHITE);
            g.drawRect(10, 10, 100, 100);
            g.drawString("Main Menu", 10, 10);
        }
    }
}

In the tick and render methods I know that I will need to tick and render only the specific STATE, so if I were in the MainMenu it would only tick and render it.

These states works in this game:

package Game;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.util.Random;

public class Game extends Canvas implements Runnable{

    private static final long serialVersionUID = 7364682855700581664L;

    public static final int WIDTH = 800, HEIGHT = WIDTH / 12 * 9;

    private Thread thread;
    private boolean running = false;

    public static boolean paused = false;
    public int diff = 0; 

    // 0 = EASY
    // 1 = NORMAL
    // 2 = HARD

    private Random r;
    private Handler handler;
    private HUD hud;
    private Spawner spawner;
    private Menu menu;

    public enum STATE {
        Menu,
        Options,
        Game,
        Select,
        Lose
    };

    public static STATE gameState = STATE.Menu;

    public Game(){
        hud = new HUD();
        handler = new Handler();
        menu = new Menu(this, handler, hud);
        this.addKeyListener(new KeyInput(handler, this));
        this.addMouseListener(menu);

        AudioPlayer.load();
        AudioPlayer.getMusic("music").loop();

        new Window(WIDTH, HEIGHT, "Test Game", this);

        spawner = new Spawner(handler, hud, this);
        r = new Random();

        if(gameState == STATE.Game){
            handler.addObject(new Player(WIDTH/2-32, HEIGHT/2-32, ID.Player, handler));
            handler.addObject(new BasicEnemy(r.nextInt(Game.WIDTH - 50), r.nextInt(Game.HEIGHT - 50), ID.BasicEnemy, handler));
        }
    }

    public synchronized void start(){
        thread = new Thread(this);
        thread.start();
        running = true;
    }

    public synchronized void stop(){
        try{
            thread.join();
            running = false;
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    public void run(){
        this.requestFocus();
        long lastTime = System.nanoTime();
        double amountOfTicks = 60.0;
        double ns = 1000000000 / amountOfTicks;
        double delta = 0;
        long timer = System.currentTimeMillis();
        int frames = 0;
        while(running){
            long now = System.nanoTime();
            delta += (now - lastTime) / ns;
            lastTime = now;
            while(delta >= 1){
                tick();
                delta--;
            }
            if(running)
                render();
            frames++;

            if(System.currentTimeMillis() - timer > 1000){
                timer += 1000;
                System.out.println("FPS: " + frames);
                frames = 0;
            }
        }
        stop();
    }

    private void tick(){
        if(gameState == STATE.Game){
            if(!paused){
                hud.tick();
                spawner.tick();
                handler.tick();

                if(HUD.PlayerHealth < 1){
                    HUD.PlayerHealth = 100;
                    //hud.setLevel(1);
                    //hud.setScore(0);
                    gameState = STATE.Lose;
                    handler.clearEnemies();
                }
            }

        }else if(gameState == STATE.Menu  || gameState == STATE.Lose || gameState == STATE.Select){
            menu.tick();
            handler.tick();
        }
    }

    private void render(){
        BufferStrategy bs = this.getBufferStrategy();
        if(bs == null){
            this.createBufferStrategy(3);
            return;
        }

        Graphics g = bs.getDrawGraphics();

        g.setColor(Color.BLACK);
        g.fillRect(0, 0, WIDTH, HEIGHT);

        handler.render(g);

        if(paused){
            g.setColor(Color.RED);
            g.drawString("PAUSED", 370, 260);
        }

        if(gameState == STATE.Game){
            hud.render(g);
        }else if(gameState == STATE.Menu || gameState == STATE.Options  || gameState == STATE.Lose || gameState == STATE.Select){
            menu.render(g);
    }

        g.dispose();
        bs.show();
    }

    public static float clamp(float var, float min, float max){
        if(var >= max)
            return var = max;
        else if(var <= min)
            return var = min;
        else
            return var;
    }

    public static void main(String args[]){
        new Game();
    }
}

解决方案

You can re-design game in two different ways.

Option 1:

Finite State machine with a pre-defined workflow : Recommended if you know all states of your game in advance and state machine is almost fixed without changes in future

Option 2:

Behavioural tress : Recommended if there are frequent changes to game behaviour. You can dynamically add behaviour to existing tree without impacting current behaviour.

Refer to below related SE question for more details.

How to implement a FSM - Finite State Machine in Java

这篇关于如何添加国家我的游戏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆