第4章 游戏的运行机制

4.1游戏中的物理运动

4.1.1模拟匀速直线运动

package com.view.test;
import java.awt.*;
public class Test{public Test(){Frame f=new Frame("my app");//顶层容器MyPanel mp=new MyPanel();//绘图容器Thread t=new Thread(mp);t.start();f.setLocation(300,200);f.setSize(300,300);f.add(mp);f.setVisible(true);}public static void main(String args[]){new Test();}
}class MyPanel extends Panel implements Runnable{private int x;private int y;private int dx;private int dy;public MyPanel(){x=50;y=50;dx=10;dy=10;}public void paint(Graphics g){ //重载paint方法g.setColor(Color.green);g.fillOval(x, y, 20, 20);}public void gameUpdate(){x=x+dx;y=y+dx;}@Overridepublic void run() {// TODO 自动生成的方法存根while(true){try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO 自动生成的 catch 块e.printStackTrace();}gameUpdate();repaint();}}
}

4.1.2 匀加速直线运动

class MyPanel extends Panel implements Runnable{private int x;private int y;private int dx;private int dy;private int dcx;private int dcy;public MyPanel(){x=50;y=50;dx=10;dy=10;dcx=1;dcy=2;}public void paint(Graphics g){ //重载paint方法g.setColor(Color.green);g.fillOval(x, y, 20, 20);}public void gameUpdate(){dx=dx+dcx;x=x+dx;dy=dy+dcy;y=y+dy;}

4.2 碰撞检测

//俄罗斯方块,判断两个物体的坐标范围是否存在交集
//边界检测,两个举证左上角坐标分别为(x1,y1)(x2,y2),
长度分别为w1和w2,长度分别为h1,h2  长宽不知谁大谁小
x1-x2<w2 && x2-x1<w1 &&
y1-y2<h2 && y2-y1<h1
//贪吃蛇,当两者的中心距离小于常数L
//中心检测
((x1+w1/2)-(x2+w2)/2))*((x1+w1/2)-(x2+w2/2))+
((y1+h1/2)-(y2+h2)/2))*((y1+h1/2)-(y2+h2/2))<L*L
//在窗口四周弹跳的小球
class MyPanel extends Panel implements Runnable{private int x;private int y;private int dx;private int dy;private int diameter;private int width;private int height;public MyPanel(){x=4;y=60;dx=20;dy=20;diameter=5;width=300;//这里有一个问题,为什么我用width=this.getWidth()得到的结果是零height=300;}public void paint(Graphics g){ //重载paint方法g.setColor(Color.green);while(true){for(int i=0;i<10000000;i++){}g.fillOval(x, y, 20, 20);gameUpdate();}}public void gameUpdate(){x+=dx;y+=dy;System.out.println(width);if((x<0)||(x>width-diameter)){dx=-dx;}if((y<0)||(y>height-diameter)){dy=-dy;}}

4.3 传递控制命令

//小球本身会动,你按下键盘控制移动方向
package com.view.test;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class Test{public Test(){Frame f=new Frame("my app");//顶层容器MyPanel mp=new MyPanel();//绘图容器Thread t=new Thread(mp);t.start();f.setLocation(300,200);f.setSize(300,300);f.add(mp);f.setVisible(true);}public static void main(String args[]){new Test();}
}class MyPanel extends Panel implements Runnable,KeyListener{private int x;private int y;private int dx;private int dy;private int diameter;private int direction;private static final int SOUTH=0;private static final int NORTH=1;private static final int EAST=2;private static final int WEST=3;public MyPanel(){x=50;y=50;dx=10;dy=10;diameter=5;addKeyListener(this);//注册键盘监听器}public void paint(Graphics g){ //重载paint方法g.setColor(Color.green);g.fillOval(x, y, 20, 20);}
 public void gameUpdate(){switch(direction){case SOUTH:y=y+dy;break;case NORTH:y=y-dy;break;case EAST:x=x+dx;break;case WEST:x=x-dx;break;}}@Overridepublic void run() {// TODO 自动生成的方法存根while(true){try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO 自动生成的 catch 块e.printStackTrace();}gameUpdate();repaint();}}@Overridepublic void keyTyped(KeyEvent e) {// TODO 自动生成的方法存根}@Overridepublic void keyPressed(KeyEvent e) {// TODO 自动生成的方法存根System.out.println("KEYPREss");int keycode=e.getKeyCode();//获取键盘按下信息switch(keycode){case KeyEvent.VK_DOWN:direction=SOUTH;break;case KeyEvent.VK_UP:direction=NORTH;break;case KeyEvent.VK_LEFT:direction=WEST;break;case KeyEvent.VK_RIGHT:direction=EAST;break;}}@Overridepublic void keyReleased(KeyEvent e) {// TODO 自动生成的方法存根}
}

4.4 游戏设计案例一:贪吃蛇游戏

4.4.1游戏整体设计

(1)主体框架类GameFrame
(2)游戏面板类GamePanel
(3)贪吃蛇类Snake
(4)食物类

//程序的主体框架
//GamePanel类的程序框架
class GamePanel extends Panel implements Runnable,KeyListener{... ...private Snake sk;//建立贪吃蛇对象private Food fd;//建立失误对象public GamePanel(){//实例化一个贪吃蛇对象,并传递一个GamePanel对象引用sk=new Snake(this);//实例化一个食物对象,并传递一个GamePanel对象和一个Snake引用fd=new Food(this,sk);}... ...public void gameUpdate(){sk.update();//更新贪吃蛇的位置坐标bk.update();//更新食物的位置坐标}public void gameRender(){Image im=new creatImage(width,height);Graphics dbg=im.getGraphics();sk.draw(dbg);//在后备缓冲区绘制贪吃蛇的图像fd.draw(dbg,fd_location);//在后备缓冲区绘制食物的图形;}public void gamePaint(){Graphics g=this.getGraphics();g.drawImage(im, 0,0,null);//将后备缓冲区的内容在屏幕上显示出来}... ...
}
//Snake类的主体框架
public class Snake {......GamePanel gameP;public Snake(GamePanel gp){......gameP=gp;}public void update(){......}public void draw(Graphics g){......}
}
//Food类的程序框架
public class Food {... ...private GamePanel gameP;private Snake snk;public Food(GamePanel gp,Snake sk){... ...gameP=gp;//通过构造方法的参数来获取GamePanel对象的引用snk=sk;//通过构造方法的参数来获取Snake对象的引用}public void update(){//更新食物坐标的相关代码}public void draw(Graphics g){//绘制食物图形的相关代码}
}

源码书中没有给全,自己补充GamaPanel是自己补充的
刚打开会报错,之后游戏正常运行,不会使用后备缓冲手法,Image im =new createImage()没有办法使用。游戏比较关键的实现是使用了循环数组解决蛇身移动的问题,涉及到引用传递对象

源码如下:

package com.view.test;
import java.awt.*;
import java.awt.event.KeyListener;
public class Test{public Test(){Frame f=new Frame("my app");//顶层容器GamePanel gp=new GamePanel();//绘图容器Thread t=new Thread(gp);t.start();f.setLocation(300,200);f.setSize(300,300);f.add(gp);f.setVisible(true);}public static void main(String args[]){new Test();}
}
package com.view.test;
import java.awt.*;
import java.awt.event.*;class GamePanel extends Panel implements Runnable,KeyListener{private int x;private int y;private int dx;private int dy;private int diameter;private int direction;int width;;int height;int fd_location;static final int SOUTH=0;static final int NORTH=1;static final int EAST=2;static final int WEST=3;private Snake sk;//建立贪吃蛇对象private Food fd;//建立失误对象public GamePanel(){addKeyListener(this);//注册键盘监听器width=300;height=300;//实例化一个贪吃蛇对象,并传递一个GamePanel对象引用sk=new Snake(this);//实例化一个食物对象,并传递一个GamePanel对象和一个Snake引用fd=new Food(this,sk);}public void paint(Graphics g){ //重载paint方法// g.setColor(Color.green);//  g.fillOval(x, y, 20, 20);sk.draw(g);fd.draw(g);}public void gameUpdate(){switch(direction){case SOUTH:y=y+dy;break;case NORTH:y=y-dy;break;case EAST:x=x+dx;break;case WEST:x=x-dx;break;}sk.update();//更新贪吃蛇的位置坐标fd.update();//更新食物的位置坐标}//  public void gameRender(){//      Image im=new createImage(width,height);
//      Graphics dbg=im.getGraphics();
//      sk.draw(dbg);//在后备缓冲区绘制贪吃蛇的图像
//      fd.draw(dbg,fd_location);//在后备缓冲区绘制食物的图形;
//  }
//
//  public void gamePaint(){//      Graphics g=this.getGraphics();
//      g.drawImage(im, 0,0,null);//将后备缓冲区的内容在屏幕上显示出来
//  }@Override
public void run() {// TODO 自动生成的方法存根while(true){try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO 自动生成的 catch 块e.printStackTrace();}gameUpdate();repaint();}}@Overridepublic void keyTyped(KeyEvent e) {// TODO 自动生成的方法存根   }@Overridepublic void keyPressed(KeyEvent e) {// TODO 自动生成的方法存根System.out.println("KEYPREss");int keycode=e.getKeyCode();//获取键盘按下信息switch(keycode){case KeyEvent.VK_DOWN:direction=SOUTH;break;case KeyEvent.VK_UP:direction=NORTH;break;case KeyEvent.VK_LEFT:direction=WEST;break;case KeyEvent.VK_RIGHT:direction=EAST;break;}}@Overridepublic void keyReleased(KeyEvent e) {// TODO 自动生成的方法存根}public int getDirection() {return direction;}public void setDirection(int direction) {this.direction = direction;}}
package com.view.test;
import java.awt.*;
public class Snake {GamePanel gameP;private Point[] body;//定义点类型数组,保存蛇蛇各个小球坐标public static final int MAXLENGTH=50;//蛇身最大长度private int head;//指示蛇头位置private int tail;//指示蛇尾位置public int length;//蛇身长度private int speed;//运行速度public int x;//蛇头小球的横坐标public int y;//蛇头小球的纵坐标public int diameter;//蛇身小球的直径public Snake(GamePanel gp){gameP=gp;body=new Point[MAXLENGTH];head=-1;tail=-1;length=1;speed=10;x=50;y=50;diameter=10;}public void update(){int direction=gameP.getDirection();//获取玩家的按键信息switch(direction){case GamePanel.SOUTH:y+=speed;break;case GamePanel.NORTH:y-=speed;break;case GamePanel.EAST:x+=speed;break;case GamePanel.WEST:x-=speed;break;}head=(head+1) % body.length;//更新蛇头指针位置;tail=(head+body.length-length+1) % body.length;//更新蛇尾指针位置body[head]=new Point(x,y);}public void draw(Graphics g){g.setColor(Color.blue);if(length>1){int i=tail;while(i!=head){//循环绘制蛇身各个小球g.fillOval(body[i].x, body[i].y, diameter, diameter);i=(i+1) % body.length;}}g.setColor(Color.red);//蛇头设置为红色g.fillOval(body[head].x,body[head].y,diameter,diameter);}
}
package com.view.test;
import java.util.Random;
import java.awt.*;
public class Food {private GamePanel gameP;private Snake snk;public Point location;//食物的坐标public Point size;//食物方块的尺寸private Random rand;//随机类的对象public Food(GamePanel gp,Snake sk){gameP=gp;//通过构造方法的参数来获取GamePanel对象的引用snk=sk;//通过构造方法的参数来获取Snake对象的引用rand=new Random();//随机地出现在屏幕上某个位置location=new Point(Math.abs(rand.nextInt() % gameP.width),Math.abs(rand.nextInt() % gameP.height));size=new Point(sk.diameter,sk.diameter);}public void update(){//更新食物坐标的相关代码//碰撞检测,判定贪吃蛇是否迟到食物if((snk.x-location.x)*(snk.x-location.x)+(snk.y-location.y)*(snk.y-location.y)<snk.diameter*snk.diameter){location=new Point(Math.abs(rand.nextInt() % gameP.width),Math.abs(rand.nextInt() % gameP.height));if(snk.length<Snake.MAXLENGTH){snk.length++;}   }}public void draw(Graphics g){//绘制食物图形的相关代码g.setColor(Color.black);g.fillRect(location.x, location.y, size.x, size.y);}
}

运行之后如下

Java游戏程序设计教程 第4章 游戏的运行机制相关推荐

  1. Unity网络多玩家游戏开发教程第1章Unity自带网络功能

    Unity网络多玩家游戏开发教程第1章Unity自带网络功能 Unity拥有大量的第三方插件,专门提供了对网络功能的支持.但是,大部分开发者第一次接触到的还是Unity自带的网络功能,也就是大家经常说 ...

  2. [libGDX游戏开发教程]使用LibGDX进行游戏开发(1)-游戏设计

    声明:本章是一个系列的开始,英文原文是<Learning libGDX Game Development>,大家请周知. [libgdx游戏开发教程]使用Libgdx进行游戏开发(2)-游 ...

  3. c语言第四章循环程序设计,C语言程序设计教程第4章-循环结构程序设计

    <C语言程序设计教程第4章-循环结构程序设计>由会员分享,可在线阅读,更多相关<C语言程序设计教程第4章-循环结构程序设计(42页珍藏版)>请在人人文库网上搜索. 1.C语言程 ...

  4. 觅凤c语言教程,C语言程序设计教程 第1章.ppt

    傣永靶莱瑞市芽星谴绥真椎匣灵租骡淬女测推谅应弥蠢仑早饲姑锗佩草隔C语言程序设计教程 第1章C语言程序设计教程 第1章 第1章 绪 论 ? ? 唆闽邹搔绕裂陶短噎诚贤希绞重垒嚷济酸凛委句枉鞘扁渗皋耿淮此 ...

  5. c语言中对用户乱输入信息处理,C语言程序设计教程 第06章.ppt

    C语言程序设计教程 第06章 第六章 函数与编译预处理 6.1 模块化程序设计与函数 6.2 函数的定义与调用 6.3 函数的递归调用 6.4 变量的作用域与存取方式 6.5 编译预处理 6.1模块化 ...

  6. C语言程序设计教程 北京邮电,C语言程序设计教程第3章_北京邮电大学出版社.ppt...

    <C语言程序设计教程第3章_北京邮电大学出版社.ppt>由会员分享,可在线阅读,更多相关<C语言程序设计教程第3章_北京邮电大学出版社.ppt(41页珍藏版)>请在人人文库网上 ...

  7. java保姆级教程—— 1.什么是游戏

    引言: Java保姆级教程是笔者在暑假时,为学弟们准备的java游戏教程,今天整理了一下,共享给网友们,笔者也是学生,若有大神发现文中存在误区,还请私信笔者. 注:java游戏保姆级教程,正在制作中, ...

  8. 游戏感:虚拟感觉的游戏设计师指南——第十七章 游戏感的原理

    这是一本游戏设计方面的好书 转自天:天之虹的博客:http://blog.sina.com.cn/jackiechueng 感谢天之虹的无私奉献 Word版可到本人的资源中下载 第十七章游戏感的原理 ...

  9. [libGDX游戏开发教程]使用libGDX进行游戏开发(12)-Action动画

    前文章节列表: 使用libGDX进行游戏开发(11)-高级编程技巧  使用libGDX进行游戏开发(10)-音乐音效不求人,程序员也可以DIY  使用libGDX进行游戏开发(9)-场景过渡 使用li ...

  10. 【Java基础系列教程】第二章 Java语言概述、配置环境变量

    一.计算机编程语言概述 1.1 语言 语言(英文:Language)是人类进行沟通交流的表达方式.例如:中国人与中国人用普通话沟通.而中国人要和英国人交流,就要学习英语.              语 ...

最新文章

  1. 谷歌浏览器实现按下按键的脚本_chrome浏览器控制台创建js脚本并执行
  2. 电脑常用工具(阅读代码、文件搜索、思维导图、图片处理、文件比较、流程图、桌面效率工具)
  3. 概率论-2.7 分布的其他特征函数
  4. json.stringify()与json.parse()的区别,json.stringify()的妙用
  5. Linux学习之第二课时--linux命令格式及命令概述
  6. [jQuery基础] jQuery事件相关
  7. axis2 java.net.url_axis2调用.net写的webservice接口实现,指定参数名
  8. [Linux] ubuntu server sudo出现sudo:must be setuid root 完美解决办法
  9. mvc路由原理 php_s-blog博客系统开发之前端路由配置
  10. Wemos基础项目之---基于WemosD1接入家庭wifi打印IP地址
  11. Unity内存/GC优化方法
  12. JSON与csv哪一个更自描述_徒步进藏和骑行进藏旅行,哪一个更辛苦
  13. 【PyTorch深度学习项目实战100例】—— 基于ResNet50实现多目标美味蛋糕图像分类 | 第51例
  14. 4399PK3366 拭目以待
  15. 为什么黑洞远程控制的屏幕传输比Radmin快
  16. hbase倒序查询_Hbase 查询Scan速度优化
  17. U1C2 文本预处理
  18. python判断素数程序_python素数判断
  19. 移动域全链路可观测架构和关键技术
  20. Qt QMenuBar QMenu和QAction

热门文章

  1. 用C++实现跨平台游戏开发之Irrlicht引擎
  2. ORB-SLAM3: An Accurate Open-Source Library for Visual, Visual-Inertial and Multi-Map SLAM
  3. GCC编译全过程解析
  4. matplotlib创建图的基本方法
  5. 这么多年都白学了,原来是方法没有用对
  6. EXCEl快速删除大量空白行
  7. tomcat之组成结构
  8. Linux配置自建 YUM 软件存储库
  9. 负载均衡常见问题之会话保持-粘滞会话(Sticky Sessions)
  10. Error: could not open `C:\Program Files\Java\jre6\lib\i386\jvm.cfg')