线程------让画面动起来

线程是大部分游戏的基础,这几天学习了线程,掌握了游戏的框架,恍然发现自己也能做出那些曾经觉得高大上的东西了。
线程:我觉得就是流水线,把一件事情交给一个或多个对象去做,而主线的控制继续。
创建线程的方法,主要有如下两种:
实现Runnable接口和继承Thread类
第一种方法实例如下
public class MyRunnable implements Runnable{  
public void run(){
System.out.println(Thread.currentThread().getName());
}
public static void main(String args[]){
MyRunnable r1 = new MyRunnable();
MyRunnable r2 = new MyRunnable();
MyRunnable r3 = new MyRunnable();
Thread thread1 = new Thread(r1,"MyThread1");
Thread thread2 = new Thread(r2);
thread2.setName("MyThread2");
Thread thread3 = new Thread(r3);
thread1.start();
thread2.start();
thread3.start();
}
}

第二种方法的实现,若把线程单独写一个类时,主要的格式,代码示例:线程弹球
public class Ball extends Thread {
public void run(){
while(true){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
//是否暂停
if(pauseFlag)
continue;
//清除小球
clearBall();
//是否结束
if(endFlag)
return;
//移动
move();
//画出小球
drawBall();
}
}

}

调用时,实例化一个线程对象,调用start()方法即可。
也可以不单独写一个类,在初始化窗体的方法中用while(true)无限循环处理,达到线程的效果。
双缓冲:利用双缓冲,可消除闪屏的动图,方法是先创建缓存图片,取出缓存图片的画布,在该画布上把所有要显示的图片画出,然后将缓存图片画到窗体上。代码示例:
//重力小球
public class Game extends JFrame{
public static void main(String[] args){
new Game().unitUI();
}
//初始化窗体
private void unitUI() {
this.setTitle("ball");
this.setSize(new Dimension(500,500));
this.setDefaultCloseOperation(3);
this.setLocationRelativeTo(null);
this.setVisible(true);
//获取窗体画布
Graphics g=this.getGraphics();
//初始坐标位置
int x=200,y=0;
//速度
int vy=0;
//速度增量
int addVy=1;
//重力小球线程
while(true){
try {//休眠时间
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//---画出缓存图片
BufferedImage buffer= new BufferedImage(this.getWidth(),
this.getHeight(),BufferedImage.TYPE_INT_BGR);
//获取画布
Graphics gh=buffer.getGraphics();
//设置颜色
gh.setColor(Color.RED);
//画出小球大小
gh.fillOval(x, y,40, 40);
//改变小球位置和速度
y+=vy;
vy+=addVy;
//判断出界
if(y>=this.getHeight()-20){
vy=-vy;
vy+=addVy;
}
//画到窗体上
g.drawImage(buffer, 0, 0, null);
}


}

}


实践:加入动态背景的弹球

import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.net.MalformedURLException;
import java.util.ArrayList;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class BallGame extends JFrame{
private static BallGame bg=new BallGame();
private ArrayList<Ball> blist=new ArrayList<Ball>();
private Ball ball;
public JPanel panel;

public static void main(String[] args){
bg.unit();
}

public void unit(){
//初始化窗体
this.setTitle("Ball");
this.setSize(new Dimension(600,600));
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(3);
//添加组件
JPanel jp=new JPanel();
jp.setPreferredSize(new Dimension(0,40));
jp.setBackground(new Color(9,2,180));
//在北边的面板上添加按钮
String[] array={"ADD","PAUSE","RESUME","END"};
for(int i=0;i<array.length;i++){
JButton jb=new JButton(array[i]);
jb.addActionListener(l);
jp.add(jb);

}
this.add(jp,BorderLayout.NORTH);

panel=new JPanel();
this.add(panel,BorderLayout.CENTER);

//添加音乐!!!!
AudioClip clip=null;
try{
clip = Applet.newAudioClip((new File("images/有你的快乐。mp3")).toURI().toURL());
}catch(MalformedURLException el){
el.printStackTrace();
}
clip.play();
//显示窗体
this.setVisible(true);
//实现线程的另一种方法
// Runnable r=new Runnanle(){
// public void run(){
// while (true{
// }
// }
// };
// Thread t=new Thread(r);
// t.start();

//取画笔
Graphics g=panel.getGraphics();
ImageIcon icon=new ImageIcon("images/b.jpg");
ImageIcon icon2=new ImageIcon("images/dxsx.gif");
int x=0,y=0;
//画图线程
while(true){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}

//------画出缓存图片------

//创建缓存图片
BufferedImage buffer=new BufferedImage(
panel.getWidth(),panel.getHeight(),
BufferedImage.TYPE_INT_RGB);
//得到画布对象
Graphics gh=buffer.getGraphics();
//画出两张背景
gh.drawImage(icon.getImage(), x, 0, null);
gh.drawImage(icon.getImage(), x+icon.getIconWidth(), 0, null);
x-=5;
//当第一张图片完全移动到窗体外,重新接到第二章图片之后
while(x+icon.getIconWidth()<=0){
x=0;
}
//遍历画出所有小球
for(int i=0;i<blist.size();i++){
Ball ball=blist.get(i);
ball.drawBall(gh);
}

gh.drawImage(icon2.getImage(), 250, 200, null);
//---在面板上画出缓存图片---
g.drawImage(buffer,0,0,null);


}
}

private ActionListener l=new ActionListener(){

public void actionPerformed(ActionEvent e) {
String s=e.getActionCommand();
if(s.equals("ADD")){
//添加到队列中,并启动线程
ball=new Ball(panel,blist);
blist.add(ball);
ball.start();

}
if(s.equals("PAUSE")){
for(int i=0;i<blist.size();i++){
ball=blist.get(i);
ball.setPauseFlag(true);
}

}
if(s.equals("RESUME")){
for(int i=0;i<blist.size();i++){
ball=blist.get(i);
ball.setPauseFlag(false);

}
}
if(s.equals("END")){
//取出对象后停止线程然后删除
while(blist.size()>0){
Ball ball=blist.get(0);
ball.setEndFlag(false);
blist.remove(0);

}

}

}

};


}


import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Ball extends Thread {
private Graphics2D g;
private JPanel jp;
private int radius;
private int x=radius,y=radius;
private int oldX=x,oldY=y;
private Color color;
private int c1,c2,c3;
private int vx;
private int vy;
private Random ran=new Random();

private Boolean pauseFlag=false;
private Boolean endFlag=false;

private ArrayList<Ball> list=new ArrayList<Ball>();

public Boolean getPauseFlag() {
return pauseFlag;
}
public void setPauseFlag(Boolean pauseFlag) {
this.pauseFlag = pauseFlag;
}
public Boolean getEndFlag() {
return endFlag;
}
public void setEndFlag(Boolean endFlag) {
this.endFlag = endFlag;
}

//构造函数
public Ball(JPanel jp,ArrayList<Ball> list){
//System.out.println("get Graphics!");
this.jp=jp;
this.list=list;
//初始化属性
unit();
}
public void run(){
while(true){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
//是否暂停
if(pauseFlag)
continue;
//清除小球
//clearBall();
//是否结束
if(endFlag)
return;
//移动
move();
//画出小球
//drawBall();
}
}
//初始化属性的方法
private void unit(){
radius=ran.nextInt(20)+20;
vx=ran.nextInt(10)+1;
vy=ran.nextInt(10)+1;
color=new Color(ran.nextInt(256),ran.nextInt(256),ran.nextInt(256));

}
//检查碰撞
private void check(int m){
//遍历队列
for(int i=0;i<list.size();i++){
Ball b=list.get(i);
if(b==this)
continue;
//判断圆心距是否大于两半径之和
int lenX=Math.abs(this.x-b.x);
int lenY=Math.abs(this.y-b.y);
int len=(int)Math.sqrt(lenX*lenX+lenY*lenY);
if(len<=this.radius+b.radius){
//横向
if(m==1){
//回到上一个位置,避免两球黏在一起
x=oldX;
y=oldY;
this.vx=-vx;
}
//纵向
if(m==2){
x=oldX;
y=oldY;
this.vy=-vy;
}
}
}

}

public void drawBall(Graphics gh){
g=(Graphics2D) gh;

//消除锯齿
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);

//取出三基色处理
int red=color.getRed();
int green=color.getGreen();
int blue=color.getBlue();

//取出当前半径
int r=radius;
int xx=x;
int yy=y;
//循环画出小球成立体效果
for(int i=0;i<20;i++){
red +=7;
green +=7;
blue +=7;
//判断范围
if(red>255)
red=255;
if(green>255)
green=255;
if(blue>255)
blue=255;
Color c=new Color(red,green,blue);
g.setColor(c);
g.fillOval(xx-r, yy-r, r*2, r*2);
r-=2;
//圆心向左偏移
xx-=1;
}

}


private void move(){
oldX=x;
x += vx;
check(1);
oldY=y;
y += vy;
check(2);
//判断出界否
if(x-radius<0){
vx=Math.abs(vx);
}
if(x+radius>jp.getWidth()){
vx=-Math.abs(vx);
}
if(y-radius<0)
vy=Math.abs(vy);
if(y+radius>jp.getHeight()){
vy=-Math.abs(vy);
}

}
}

效果截图
[img]http://dl2.iteye.com/upload/attachment/0099/1613/c6252db8-94ea-32a8-9740-a9d948c3ca15.jpg[/img]

这是做的一个小练习,还有很多不足,在其他的应用中仍需继续学习和完善。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值