关闭

[学习笔记]小型java游戏引擎_1

492人阅读 评论(0) 收藏 举报
分类:

https://www.youtube.com/playlist?list=ELp5mgUw5g9EY      上的教学视频学习笔记

主要难点:

1.如何用线程 和 循环 控制游戏的 开始,停止状态

2.如何用循环解决 游戏画面 帧数的渲染和控制

3.一些图形图像,缓冲的类

Image, BufferedImage, BufferStrategy, Canvas



代码如下:

package com.main;

import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.util.Random;
import javax.swing.JFrame;

public class Game extends Canvas implements Runnable
{
	public JFrame jframe;
	public final int WIDTH = 400;  //界面宽度
	public final int HEIGHT = 300; //界面高度
	public final int SCALE = 2;    //缩放比例
	public boolean GAME_RUNNING_STATE = false;  //游戏运行状态
	
	public int tick_count = 0;  //统计已经运行过的总帧数  
	private BufferedImage buf_img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); //游戏界面的缓冲区? 
	private int[] pixels = ( (DataBufferInt)buf_img.getRaster().getDataBuffer() ).getData(); //游戏界面的所有像素?
	
	public Game()
	{
		jframe = new JFrame();
		setMaximumSize(new Dimension( WIDTH*SCALE, HEIGHT*SCALE ));
		setMinimumSize(new Dimension( WIDTH,HEIGHT) );
		setPreferredSize(new Dimension(WIDTH, HEIGHT));
		
		jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		jframe.setResizable(false);
		jframe.setVisible(true);
		jframe.setLocationRelativeTo(null);
		
		//布局管理器
		jframe.setLayout( new BorderLayout() );
		jframe.add(this,BorderLayout.CENTER);  //把游戏界面放进这个jrame里面的borderLayout里面
		jframe.pack();
		
			
	}
	
	private synchronized void start()
	{
		//启动游戏线程
		new Thread(this).start();   //即调用run()函数
		GAME_RUNNING_STATE = true;
	}
	
	private synchronized void stop()
	{
		GAME_RUNNING_STATE = false;
	}
	
	
	public void run() 
	{
		long old_time_ns = System.nanoTime();  //运行进入到本函数的时间(纳秒级别) 1秒 = 1000 000 000 纳秒(ns)
		long old_time_ms = System.currentTimeMillis(); //毫秒级别
		double nsPerTick = 1000000000D/60D;  //我们希望游戏   每秒60帧,那么每帧为    1000000000/60 纳秒
		int ticks = 0;   //记录理论上的帧数
		int frames = 0;  //记录实际渲染的帧数
		double ticks_has_gone = 0;   //记录当前已经走了多少帧
		
		//开始循环
		while( GAME_RUNNING_STATE )
		{
			long now_time_ns = System.nanoTime();  //得出当前时间
			ticks_has_gone += (now_time_ns - old_time_ns) / nsPerTick;  // 时间差/每帧所需时间  = 走过的帧数,
			old_time_ns = now_time_ns;  //现在的时间在下一次循环就是旧时间
			boolean shouldRender = false;  //是否进行渲染
			
			//用走过的帧数是否>=1来判断 当前时间是否够一帧
			if( ticks_has_gone >=1 )   //如果 刚好走够一帧
			{
				ticks++;  //加上一帧
				tick();   //每一帧所对应的操作,例如图形渲染等
				ticks_has_gone -= 1;  //清零,继续用ticks_has_gone来记录是否走满一帧
				shouldRender = true;
			}
			
			if(shouldRender)
			{
				render();//渲染
				frames++;
			}
			
			if( System.currentTimeMillis() - old_time_ms >= 1000 )
			{
				//每过一秒 就对运行的帧数 做一次统计
				old_time_ms += 1000;  //更新循环里面的old_timer 供下一次循环使用
				System.out.println( frames + "  " + ticks);
				frames = 0;  //清零
				ticks = 0;  //清零
			}
			
		}
	}
	
	public void tick()
	{
		tick_count++;
		
		for(int i=0; i< pixels.length; i++)
		{
			//更改每一个像素
			//pixels[i] = i + tick_count; //没有特别的颜色意义,只是看看渲染有变化效果
			pixels[i] = i * tick_count; //不懂图形学 不过好象可以在这里做出很多很炫的渲染效果
			//pixels[i] = i * new Random().nextInt();
			
		}
	}
	
	public void render()
	{
		BufferStrategy buf_str = getBufferStrategy();
		if( buf_str == null)
		{
			createBufferStrategy(3);  //三层缓冲
			return;
		}
		
		//渲染
		Graphics g = buf_str.getDrawGraphics();
		g.setColor( Color.blue );
		//g.fillRect(0, 0, getWidth(), getHeight() );
		g.drawImage(buf_img, 0, 0, getWidth(), getHeight(), null );
		g.drawRect(0, 0, getWidth(), getHeight());
		g.dispose();
		buf_str.show();
		
	}
	
	
	public static void main(String[] args) {
		new Game().start();
	}
	
}




0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:73480次
    • 积分:1611
    • 等级:
    • 排名:千里之外
    • 原创:93篇
    • 转载:2篇
    • 译文:0篇
    • 评论:24条
    微博