利用小游戏学习多线程之飞机躲子弹
来源:互联网 发布:市场份额数据优缺点 编辑:程序博客网 时间:2024/06/07 20:25
新的游戏思路如下:
通过鼠标来点击屏幕,在鼠标点击的位置生成小球,并且颜色随机。点击一次启动一个线程,一个线程代表一个小球,小球可以随机移动,假如小飞机碰到小球,则小球停止移动,即线程死亡。代码只有三个类,复制起来比较容易。
PlaneBall3.java
package com.study.thread;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import com.game.util.Constant;
import com.game.util.GameUtil;
public class PlaneBall3 extends Frame{
long starttime;
int x = 200;
int y = 100;
private boolean renew = true;
Plane plane = new Plane("images/plane.PNG",50,50);
private java.util.List<Ball> balls = new ArrayList<>();
int frame_x;
int frame_y;
boolean title=true;
public void launch() {
setSize(600, 400);
setLocation(200,200);
setVisible(true);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
Point point = java.awt.MouseInfo.getPointerInfo().getLocation();
frame_x=getX();
frame_y=getY();
if(renew==true){
new BallThread((point.x-frame_x), (point.y-frame_y)).start();
}
title = false;
}
});
addKeyListener(new KeyMonitor());
starttime = System.currentTimeMillis();
}
class BallThread extends Thread{
int x;
int y;
public BallThread(int x, int y) {
this.x = x;
this.y = y;
}
public void run(){
Ball ball = new Ball();
ball.x = x;
ball.y = y;
balls.add(ball);
for(int i = 0;i<5000;i++){
ball.move();
if(ball.getRec().intersects(plane.getRec())){
break;
}
try {
Thread.currentThread().sleep(40);
} catch (InterruptedException e) {
e.printStackTrace();
}
repaint();
}
}
}
@Override
public void paint(Graphics g) {
g.drawString("游戏时间:"+(System.currentTimeMillis()-starttime)/1000+"s", 20, 50);
for (Ball ball : balls)
{
if(ball.visible == true){
Color color = new Color(
(new Double(Math.random() * 128)).intValue()+50,
(new Double(Math.random() * 128)).intValue()+50,
(new Double(Math.random() * 128)).intValue()+50);
g.setColor(color);
g.fillOval(ball.x, ball.y, 15, 15);
}
}
plane.draw(g);
if(title==true){
Font font2 = new Font("微软雅黑", Font.ITALIC, 40);
g.setFont(font2);
g.drawString("请点击窗体开始游戏", 100, 200);
}
}
private Color backColor = new Color(0x65, 0xc2, 0x94);
private Image offScreenImage = null;
public void update(Graphics g) {
if (this.offScreenImage == null) {
this.offScreenImage = this.createImage(600, 400);
}
Graphics goff = offScreenImage.getGraphics();
Color c = goff.getColor();
goff.setColor(this.backColor);
goff.fillRect(0, 0, 600, 400);
goff.setColor(c);
paint(goff);
g.drawImage(this.offScreenImage, 0, 0, null);
}
class KeyMonitor extends KeyAdapter{
@Override
public void keyPressed(KeyEvent e) {
plane.adddirection(e);
}
@Override
public void keyReleased(KeyEvent e) {
plane.reduceirection(e);
}
}
public static void main(String[] args) {
new PlaneBall3().launch();
}
class Ball{
int x;
int y;
double degree = Math.PI*2*Math.random();
boolean visible = true;
public Ball() {}
public Ball(int x, int y) {
this.x = x;
this.y = y;
}
public void move(){
x +=10*Math.cos(degree);
y +=10*Math.sin(degree);
if(x<0||x>600-20){
degree = Math.PI-degree;
}
if(y<0||y>400-20){
degree = -degree;
}
}
public Rectangle getRec(){
return new Rectangle(x, y, 20, 20);
}
}
}
Plane.java
package com.study.thread;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
public class Plane {
Image img;
public double x;
public double y;
public boolean left,right,up,down;
public int speed = 7;
public int width,height;
public Rectangle getRec(){
return new Rectangle((int)x, (int)y, width, height);
}
public void draw(Graphics g){
g.drawImage(img, (int)x, (int)y, null);
move();
}
public void move(){
if(left){
x -=speed;
if(x<0){
x = 0;
}
}
if(right){
x +=speed;
if(x>600-width){
x = 600-width;
}
}
if(up){
y -=speed;
if(y<height){
y = height;
}
}
if(down){
y +=speed;
if(y>400-height){
y = 400-height;
}
}
}
public void adddirection(KeyEvent e){
switch (e.getKeyCode()) {
case KeyEvent.VK_LEFT:
left = true;
break;
case KeyEvent.VK_RIGHT:
right = true;
break;
case KeyEvent.VK_UP:
up = true;
break;
case KeyEvent.VK_DOWN:
down = true;
break;
default:
break;
}
}
public void reduceirection(KeyEvent e){
switch (e.getKeyCode()) {
case KeyEvent.VK_LEFT:
left = false;
break;
case KeyEvent.VK_RIGHT:
right = false;
break;
case KeyEvent.VK_UP:
up = false;
break;
case KeyEvent.VK_DOWN:
down = false;
break;
default:
break;
}
}
public Plane(){
}
public Plane(String path,double x,double y){
this.img = GameUtil.getImage(path);
this.width = img.getWidth(null);
this.height = img.getHeight(null);
this.x = x;
this.y = y;
}
}
GameUtil.java
package com.study.thread;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
public class GameUtil {
private GameUtil(){}
public static Image getImage(String path){
URL u=GameUtil.class.getClassLoader().getResource(path);
BufferedImage img=null;
try {
img = ImageIO.read(u);
} catch (IOException e) {
e.printStackTrace();
}
return img;
}
}
游戏运行起来的时候发现,假如小球越多,小飞机的速度就会越快,想了想是因为每个小球都代表了一个线程,每次产生小球的时候都会调用repaint()这个方法,小球越多,调用次数就会越来越多,小飞机的速度就会加快。假如并不想让小飞机的速度加快,可以直接在一个线程里面实现产生多个小球,然后控制这个线程的死亡与否,便可以实现我之前一直想要的不点击运行按钮便重新开始游戏。
之前打算写的小游戏是利用键盘控制屏幕中的小飞机来躲避子弹,假如飞机碰到子弹则游戏结束。
这个小游戏只要利用重写paint()方法即可实现。
代码如下:
PlaneGameFrame.java
package com.game.plane;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import com.game.util.Bullet;
import com.game.util.GameUtil;
import com.game.util.MyFrame;
import com.game.util.Plane;
public class PlaneGameFrame extends MyFrame {
Plane plane = new Plane("image/plane.PNG",50,50);
Boolean Game = true;
ArrayList bulletlist = new ArrayList();
long start = System.currentTimeMillis();
Image sky = GameUtil.getImage("image/sky.jpg");
public void paint(Graphics g){
if(Game==true){
plane.draw(g);
for(int i=0;i<18;i++){
Bullet bullet = new Bullet();
bullet = (Bullet) bulletlist.get(i);
bullet.draw(g);
if(plane.getRec().intersects(bullet.getRec())){
Game = false;
}
}
}else {
Font font = new Font("宋体", Font.BOLD, 100);
g.setFont(font);
g.drawString("game over", 200, 200);
Font font2 = new Font("微软雅黑", Font.ITALIC, 30);
g.setFont(font2);
g.drawString("游戏时间:"+(System.currentTimeMillis()-start)/1000+"s", 300, 500);
}
}
public void launchFrame(){
super.launchFrame();
addKeyListener(new KeyMonitor());
for(int i=0;i<18;i++){
Bullet b = new Bullet();
bulletlist.add(b);
}
}
class KeyMonitor extends KeyAdapter{
@Override
public void keyPressed(KeyEvent e) {
plane.adddirection(e);
}
@Override
public void keyReleased(KeyEvent e) {
plane.reduceirection(e);
}
}
public static void main(String[] args) {
new PlaneGameFrame().launchFrame();
}
}
Ball.java
package com.game.util;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
public class Ball {
public int x;
public int y;
public double degree = -Math.PI/6;
Image img ;
private int width;
public int height;
public Ball(){
}
public Ball(String imgpath,int x,int y){
img = GameUtil.getImage(imgpath);
width = img.getWidth(null);
height = img.getHeight(null);
this.x = x;
this.y = y;
}
public void move(long start){
x +=Constant.SPEED*Math.cos(degree);
y +=Constant.SPEED*Math.sin(degree);
if(x<0||x>500-25){
degree = Math.PI-degree;
}
if(y<0){
degree = -degree;
}
if(y>500-25){
degree = -degree;
}
}
public Rectangle getRec(){
return new Rectangle(x, y, width, height);
}
public void draw(Graphics g){
g.drawImage(img, x, y, null);
}
}
Bullet.java
package com.game.util;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
public class Bullet {
double x,y;
int speed = 10;
double degree;
int width = 10;
int height = 10;
public Bullet(){
degree = Math.random()*Math.PI*2;
x = Constant.GAME_WIDTH/2;
y = Constant.GAME_HEIGHT/2;
}
public Rectangle getRec(){
return new Rectangle((int)x, (int)y, width, height);
}
public void draw(Graphics g){
Color color = g.getColor();
g.setColor(Color.RED);
g.fillOval((int)x, (int)y, width, height);
x +=speed*Math.cos(degree);
y +=speed*Math.sin(degree);
if(x<0||x>Constant.GAME_WIDTH-width){
degree = Math.PI-degree;
}
if(y<height||y>Constant.GAME_HEIGHT-height){
degree = -degree;
}
g.setColor(color);
}
}
Constant.java
package com.game.util;
public class Constant {
public static final int GAME_WIDTH = 800;
public static final int GAME_HEIGHT = 600;
public static final int SPEED = 20;
}
GameUtil.java
package com.game.util;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
public class GameUtil {
private GameUtil(){}
public static Image getImage(String path){
URL u=GameUtil.class.getClassLoader().getResource(path);
BufferedImage img=null;
try {
img = ImageIO.read(u);
} catch (IOException e) {
e.printStackTrace();
}
return img;
}
}
MyFrame.java
package com.game.util;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class MyFrame extends Frame {
public void launchFrame(){
setSize(Constant.GAME_WIDTH,Constant.GAME_HEIGHT);
setVisible(true);
new PaintThread().start();
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent event){
System.exit(0);
}
});
}
// private Image offScreenImage = null;
// public void update(Graphics g){
// if(offScreenImage == null)
// offScreenImage = this.createImage(Constant.GAME_WIDTH,Constant.GAME_HEIGHT);
// Graphics gOff = offScreenImage.getGraphics();
// paint(gOff);
// g.drawImage(offScreenImage, 0, 0, null);
// }
private Color backColor = new Color(0x65, 0xc2, 0x94);
private Image offScreenImage = null;
public void update(Graphics g) {
if (this.offScreenImage == null) {
this.offScreenImage = this.createImage(Constant.GAME_WIDTH, Constant.GAME_HEIGHT);
}
Graphics goff = offScreenImage.getGraphics();
Color c = goff.getColor();
goff.setColor(this.backColor);
goff.fillRect(0, 0, Constant.GAME_WIDTH, Constant.GAME_HEIGHT);
goff.setColor(c);
paint(goff);
g.drawImage(this.offScreenImage, 0, 0, null);
}
class PaintThread extends Thread {
public void run() {
while(true) {
repaint();
try {
Thread.sleep(40);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
Plane.java
package com.game.util;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
public class Plane {
Image img;
public double x;
public double y;
public boolean left,right,up,down;
public int speed = 10;
public int width,height;
public Rectangle getRec(){
return new Rectangle((int)x, (int)y, width, height);
}
public void draw(Graphics g){
g.drawImage(img, (int)x, (int)y, null);
move();
}
public void move(){
if(left){
x -=speed;
if(x<0){
x = 0;
}
}
if(right){
x +=speed;
if(x>500-width){
x = 500-width;
}
}
if(up){
y -=speed;
if(y<height){
y = height;
}
}
if(down){
y +=speed;
if(y>500-height){
y = 500-height;
}
}
}
public void adddirection(KeyEvent e){
switch (e.getKeyCode()) {
case KeyEvent.VK_LEFT:
left = true;
break;
case KeyEvent.VK_RIGHT:
right = true;
break;
case KeyEvent.VK_UP:
up = true;
break;
case KeyEvent.VK_DOWN:
down = true;
break;
default:
break;
}
}
public void reduceirection(KeyEvent e){
switch (e.getKeyCode()) {
case KeyEvent.VK_LEFT:
left = false;
break;
case KeyEvent.VK_RIGHT:
right = false;
break;
case KeyEvent.VK_UP:
up = false;
break;
case KeyEvent.VK_DOWN:
down = false;
break;
default:
break;
}
}
public Plane(){
}
public Plane(String path,double x,double y){
this.img = GameUtil.getImage(path);
this.width = img.getWidth(null);
this.height = img.getHeight(null);
this.x = x;
this.y = y;
}
}
这样勉强就可以玩游戏了,但是我玩了几回,发现实在太麻烦了,每次结束都需要重新点击运行按钮,我就想可不可以在游戏结束之后重新开始游戏呢,几次尝试之后,我觉着利用单线程的boolean变量实现起来很麻烦,这样自然会想到多线程。
新的游戏思路如下:
通过鼠标来点击屏幕,在鼠标点击的位置生成小球,并且颜色随机。点击一次启动一个线程,一个线程代表一个小球,小球可以随机移动,假如小飞机碰到小球,则小球停止移动,即线程死亡。
- 利用小游戏学习多线程之飞机躲子弹
- 小游戏之飞机躲子弹
- Unity3D学习之飞机发射子弹。
- python打飞机躲子弹
- 飞机大战之三:添加子弹
- 子弹小游戏^^
- 飞机大战03之飞机发射子弹,添加敌人
- unity3d开发 打飞机小游戏(三)(飞机子弹设置)
- unity学习之飞机大战制作 关键点(三) 设置子弹的生成和移动
- unity学习之飞机大战制作 关键点(六) 子弹与敌机之间的碰撞
- unity学习之飞机大战制作 关键点(MAX) 成品小游戏飞机大战
- Java窗体实现飞机躲子弹游戏
- 第三十九天 一乐在其中—Android的小游戏打飞机(三)让子弹飞
- python-小游戏(打飞机)v1.2(三发子弹)
- 基于cocos2dx的飞机大战学习[四]-添加英雄子弹
- 黑马学习-------------------android小游戏--飞机大战(初步)
- 学习Swing做的打飞机小游戏
- Java小游戏之打飞机(一)
- 自学js建议
- leetcode 153|154. Find Minimum in Rotated Sorted Array 1|2
- 人工智能学习谱图
- SVN插件 防遗忘
- python3 sort sorted 函数应用
- 利用小游戏学习多线程之飞机躲子弹
- java中获取当前类名,方法名
- ojdbc.jar不同oracle版本下载地址
- 消息队列-ActiveMQ学习笔记(一)-JMS介绍与环境搭建
- 设计23式—命令
- 类和对象的关系
- Git如何进行分支管理?
- java虚拟机、垃圾回收、多线程
- Deep Learning回顾#之LeNet、AlexNet、GoogLeNet、VGG、ResNet