zoukankan      html  css  js  c++  java
  • 手把手一步一步教你使用Java开发一个大型街机动作闯关类游戏01游戏窗口

    项目源码

    项目源码

    游戏配置信息类

    Config.java 没什么解释的。

    package config;
    
    public class Config {
    	public final static String TITEL = "fight_to_the_end";
    	public final static String VERSION = "v1.0";
    	
    	public final static byte BUFFERS = 2;
    	public final static int FPS = 60;
    
    	public final static boolean DEBUG = true;
    }
    
    

    主函数Main.java

    package main;
    
    
    public class Main
    { 
    	public static void main(String  [] args)
    	{
    		GameApp app = new GameApp();
    	}
    
    }
    

    创建了一个GameApp对象,GameApp对象是我们游戏的主循环。
    GameApp.java

    package main;
    
    import config.Config;
    
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.image.BufferStrategy;
    
    
    public class GameApp {
    	private boolean _gameRunning = true;
    	private Frame _frm;
    
    	public GameApp(){
    		try{
    			_frm = new Frame();
    			_frm.setUndecorated(true);
    			_frm.setIgnoreRepaint(true);
    			_frm.setTitle("");
    
    			JButton button = new JButton("close");
    			button.addActionListener(new ActionListener() {
    				public void actionPerformed(ActionEvent e) {
    					_gameRunning = false;
    					_frm.dispose();
    				}
    			});
    			_frm.add(button);
    			_frm.setSize(800,600);
    			_frm.setLocation(100, 100);
    			_frm.setVisible(true);
    			_frm.setResizable(false);
    			_frm.createBufferStrategy(Config.BUFFERS);
    	        _gameLoop();
    
    		}catch (Exception e) {
                e.printStackTrace();
    		}finally{
    			System.exit(0);
    		}
    	}
    

    GameApp构造函数主要做了2件事:
    1.创建游戏窗口;
    2.启动game主循环_gameLoop()

                _frm = new Frame();
                _frm.setUndecorated(true);
                _frm.setIgnoreRepaint(true);
                _frm.setTitle("");
    
                JButton button = new JButton("close");
                button.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        _gameRunning = false;
                        _frm.dispose();
                    }
                });
                _frm.add(button);
                _frm.setSize(800,600);
                _frm.setLocation(100, 100);
                _frm.setVisible(true);
                _frm.setResizable(false);
                _frm.createBufferStrategy(Config.BUFFERS);
                _gameLoop();
    

    创建窗体,设置窗体大小,位置,可见性,窗口上添加了一个大按钮,点击后可以关闭本窗体。

    其中比较重要的一行代码是:

     _frm.createBufferStrategy(Config.BUFFERS);
    

    设置窗体的缓冲策略为双缓冲。就是我们先将游戏每一帧(包含很多图片,我们下一节详细介绍)的全部数据,先全部画在内存中,再一次性的粘贴到屏幕上。这样可以提高绘制效率,减少屏幕闪烁。
    想象一下,有一个双面白板,可以翻转显示一侧或另一侧。前面是显示器(玩家看到的屏幕),而背面是隐藏的,只有计算机可以“看到”它。每一帧,都在背面(内存中)绘制所有图画 - 每个角色,每个子弹,每个闪耀的光线等等。然后,当完成后,将白板翻转并显示(将所有图片数据从内存拷贝到屏幕上)。

    接下来我们看_gameLoop()方法:

    	private void _gameLoop(){
    		BufferStrategy buff = _frm.getBufferStrategy();
    		while(_gameRunning){
    			Graphics2D g = (Graphics2D)buff.getDrawGraphics();
    
    			// Rendering
    			_initRendering(g);
    
    			if(Config.DEBUG){
    				_displayInfoText(g);
    			}
    
    			g.dispose();
    
    			if (!buff.contentsLost())
    		    {
    				buff.show();
    		    }
    			Toolkit.getDefaultToolkit().sync();
    
    		    try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    		}
    	}
    	private void _initRendering(Graphics2D g){
    		g.setColor(Color.black);
    		g.fillRect(0, 0, 800, 600);
    	}
    
    	private void _displayInfoText(Graphics2D g){
    		g.setColor(Color.white);
    		g.drawString(Config.TITEL+ " "+ Config.VERSION, 20, 20);
    	}
    

    该方法整体结构是一个死循环,每次循环Thread.sleep(1); 让主线程睡眠1毫秒,让出cpu时间片;让其他进程得到执行,防止cpu使用率过高。

    Graphics2D g = (Graphics2D)buff.getDrawGraphics();
    
                // Rendering
                _initRendering(g);
    
                if(Config.DEBUG){
                    _displayInfoText(g);
                }
    
                g.dispose();
    

    在内存中描画:填充一个黑色矩形,并且显示一个白色的字符串。

    if (!buff.contentsLost())
                {
                    buff.show();
                }
                Toolkit.getDefaultToolkit().sync();
    
    

    将内存中的图像,粘贴到屏幕上。

    本节最终效果

    运行程序,显示一个黑窗体,点击任意位置,窗体关闭。

  • 相关阅读:
    Kafka副本管理—— 为何去掉replica.lag.max.messages参数
    Kafka0.8.2.1删除topic逻辑
    【原创】如何确定Kafka的分区数、key和consumer线程数
    【原创】Kafka console consumer源代码分析(二)
    QGIS源码解析和二次开发
    点云数据中的三维信息提取pcl
    Halcon10.0 + VS2010
    Halcon链接库
    python调用Opencv库和dlib库
    cvtColor
  • 原文地址:https://www.cnblogs.com/songboriceboy/p/15744076.html
Copyright © 2011-2022 走看看