线程
线程的概念
像以往我们做一个图板或者做一个自动运行的程序时在一个方法进行执行时,程序未执行完成时是无法关闭以及进行其他操作的,但是在继承线程Thread后就可以实现在线程程序运行时执行其他操作。
线程的基本语法
首先将于要执行线程的类继承Thread
public class A extends Thread{
}
之后再重写Thread中的run方法
public void run(){
while(true){
this.move();
}
}
最后在mian函数中创建A对象,并调用A的start方法,注意这里不是通过调用run方法启动,而是调用start方法启动。
public static void main(String args[]){
A a =new A();
a.start();
}
运行程序后可以发现move方法在不断被执行但是与此同时我们可以进行关闭等其他操作。
大球吃小球
整体思路
这个游戏模仿大鱼吃小鱼的小游戏,通过创建不同大小的小球进行吃与被吃的过程,玩家控制一个小球拥有可升级的选项,其他小球拥有真侦测其身边小球的功能,当其他小球比当前小球级别高时反向逃离该小球,反之向该小球移动。
代码实现
首先创建画板对象,也是该游戏的主场景,设置背景为绿色,创建键盘监听器控制玩家小球,并监听画布。
public class UI extends JFrame{
public static void main(String args[]){
UI ui = new UI();
ui.startUI();
}
public void startUI(){
this.setTitle("zoo");// 标题
this.setSize(1200,700);// 窗口大小
this.setResizable(false);// 窗口是否可动
this.setDefaultCloseOperation(3);// 关闭时退出程序
setLocationRelativeTo(null);//居中
this.setVisible(true);
Graphics g = this.getGraphics();
Listener l =new Listener(g);
this.addKeyListener(l);
}
public void paint(Graphics g){
super.paint(g);
g.setColor(Color.green);
g.fillRect(0, 0, 1200, 750);
System.out.println(1);
}
}
创建小球类继承Thread(但小球类不会用到,用于之后玩家类重写run方法),创建用于储存小球对象的ArrayList,并为小球设置等级0-4级,根据等级设定颜色大小以及速度,然后创建move方法设置小球的移动规律,例如触碰到边界,遭遇其他小球进行判断能否被吃。再创建侦测的方法判断侦测范围内小球的等级以及方位进行移动。
public class Animal extends Thread{
int id,speed,x,y,sx,sy,size;
ArrayList<Animal> list;
Graphics g;
Random m = new Random();
public Animal(int x,int y,int id,Graphics g,ArrayList<Animal> list){
this.x=x;
this.y= y;
if(id<5){
this.id =id;
}else{
this.id=4;
}
this.g =g;
this.speed = 10 - 2*id;
this.size = 20+10*id;
this.list =list;
sx = m.nextInt(speed+1);
sy = m.nextInt(speed+1);
}
public void move(){
int l,x1,y1,s;
if (x < 0) {
sx = m.nextInt(speed+1);
sy =speed-sx;
} else if (x > 1200) {
sx = -m.nextInt(speed+1);
sy = speed+sx;
} else if (y < 0) {
sy = m.nextInt(speed+1);
sx = speed -sy;
} else if (y > 650) {
sy = -m.nextInt(speed+1);
sx = speed +sy;
}
for (int i = 0; i < list.size(); i++) {
if(list.get(i)!=null){
x1 = list.get(i).x ;
y1 = list.get(i).y ;
l = (x1 - x) * (x1 - x ) + (y1 - y) * (y1 - y);
s =(list.get(i).size/2+size/2)*(list.get(i).size/2+size/2);
if(l < s&&x!=list.get(i).x){
if(id>list.get(i).id){
g.setColor(Color.green);
g.fillOval(list.get(i).x-list.get(i).size/2, list.get(i).y-list.get(i).size/2, list.get(i).size,list.get(i).size);
list.set(i, null);
}else if(id==list.get(i).id){
sx=-sx;
sy=-sy;
}
}
}
}
g.setColor(Color.green);
g.fillOval(x-size/2, y-size/2, size, size);
x += sx;
y += sy;
this.darw();
}
public void darw(){
Color c = null;
if(this.id==0){
c=Color.white;
}else if(this.id ==1){
c=Color.ORANGE;
}else if(this.id == 2){
c=Color.gray;
}else if(this.id == 3){
c=Color.yellow;
}else if(this.id == 4){
c=Color.black;
}
g.setColor(c);
g.fillOval(x-size/2, y-size/2, size, size);
}
public void Existence(){
int l,x1,y1;
for(int i=0;i<list.size();i++){
if(list.get(i)!=null){
x1=list.get(i).x;
y1= list.get(i).y;
l=(y-y1)*(y-y1)+(x-x1)*(x-x1);
if(l < 10000){
if(id > list.get(i).id){
this.a(list.get(i));
}else if(id < list.get(i).id){
this.b(list.get(i));
}
}
}
}
}
public void run() {
while (true) {
try {
Thread.sleep(80);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
for(int i=1;i<list.size();i++){
if(list.get(i)!=null){
list.get(i).Existence();
list.get(i).move();
}
}
}
}
public void a(Animal n){
int x1=n.x;
int y1= n.y;
if(x-x1>=0&&y-y1>=0){
if(x-x1>=y-y1){
sx =-speed;
sy = -((y-y1)/(x-x1))*speed;
}else{
sy =-speed;
sx = -((x-x1)/(y-y1))*speed;
}
}else if(x-x1<=0&&y-y1>=0){
if(x1-x>=y-y1){
sx = speed;
sy = -((y-y1)/(x-x1))*speed;
}else{
sy =speed;
sx = -((x-x1)/(y-y1))*speed;
}
}else if(x-x1>=0&&y-y1<=0){
if(x-x1>=y1-y){
sx = -speed;
sy = ((y-y1)/(x-x1))*speed;
}else{
sy =-speed;
sx = ((x-x1)/(y-y1))*speed;
}
}else if(x-x1<=0&&y-y1<=0){
if(x1-x>=y-y1){
sx = speed;
sy = ((y-y1)/(x-x1))*speed;
}else{
sy =speed;
sx = ((x-x1)/(y-y1))*speed;
}
}
}
public void b(Animal n){
int x1=n.x;
int y1= n.y;
if(x-x1>=0&&y-y1>=0){
if(x-x1>=y-y1){
sx =speed;
sy = ((y-y1)/(x-x1))*speed;
}else{
sy =speed;
sx =((x-x1)/(y-y1))*speed;
}
}else if(x-x1<=0&&y-y1>=0){
if(x1-x>=y-y1){
sx = -speed;
sy = ((y-y1)/(x-x1))*speed;
}else{
sy =-speed;
sx = ((x-x1)/(y-y1))*speed;
}
}else if(x-x1>=0&&y-y1<=0){
if(x-x1>=y1-y){
sx = speed;
sy = -((y-y1)/(x-x1))*speed;
}else{
sy =speed;
sx = -((x-x1)/(y-y1))*speed;
}
}else if(x-x1<=0&&y-y1<=0){
if(x1-x>=y-y1){
sx = -speed;
sy = -((y-y1)/(x-x1))*speed;
}else{
sy =-speed;
sx = -((x-x1)/(y-y1))*speed;
}
}
}
}
然后创建玩家小球继承小球类,重写属性,重写玩家自己的move方法,定义移动方式,以及升级的经验条,以及玩家的等级(可大于小球的最高的等级),最后重写run方法,让小球数量等级根据玩家等级变化,且实现list中所有小球的移动。
public class Player extends Animal {
int exp = 0;
public Player(int x, int y, int id, Graphics g, ArrayList<Animal> list) {
super(x, y, id, g, list);
// TODO Auto-generated constructor stub
if(id<6){
this.id = id;
}else{
this.id = 5;
}
sx = 0;
sy = 0;
}
public void move(){
int x1,y1,l,s;
if (x < 0&&sx<0) {
sx =0;
} else if (x > 1200&&sx>0) {
sx=0;
} else if (y < 0&&sy<0) {
sy=0;
} else if (y > 650&&sy>0) {
sy=0;
}
for (int i = 0; i < list.size(); i++) {
if(list.get(i)!=null){
x1 = list.get(i).x ;
y1 = list.get(i).y ;
l = (x1 - x) * (x1 - x ) + (y1 - y) * (y1 - y);
s =(list.get(i).size/2+size/2)*(list.get(i).size/2+size/2);
if(l < s&&x!=list.get(i).x){
if(id>list.get(i).id){
g.setColor(Color.green);
g.fillOval(list.get(i).x-list.get(i).size/2, list.get(i).y-list.get(i).size/2, list.get(i).size,list.get(i).size);
list.set(i, null);
size++;
this.up();
}
}
}
}
g.setColor(Color.green);
g.fillOval(x-size/2, y-size/2, size, size);
x += sx;
y += sy;
this.darw();
}
public void darw(){
Color c = null;
if(this.id==0){
c=Color.white;
}else if(this.id ==1){
c=Color.ORANGE;
}else if(this.id == 2){
c=Color.gray;
}else if(this.id == 3){
c=Color.yellow;
}else if(this.id == 4){
c=Color.black;
}else if(this.id ==5){
c=Color.red;
}
g.setColor(Color.red);
g.fillOval(x-size/2, y-size/2, size, size);
g.setColor(c);
g.fillOval(x-size/2+1, y-size/2+1, size-2, size-2);
}
public void up() {
exp++;
if (exp == 10) {
id++;
exp = 0;
}
g.setColor(Color.white);
g.fillRect(0, 680, 1200, 20);
g.setColor(Color.blue);
g.fillRect(0, 680, 120*this.exp, 20);
}
public void run() {
while (true) {
System.out.println(exp);
int m = 0;
if(id>3){
m=3;
}
int n = 0;
try {
Thread.sleep(80);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
for (int i = 0; i < list.size(); i++) {
if (list.get(i) != null) {
if (list.get(i).id > id) {
m++;
} else if (list.get(i).id < id) {
n++;
}
}
}
if (m < 3) {
Animal a = new Animal(ran(1200), ran(700), id + 1, g, list);
list.add(a);
}
if (n < 10) {
Animal b = new Animal(ran(1200), ran(700), id - 1, g, list);
list.add(b);
}
for (int i = 1; i < list.size(); i++) {
if (list.get(i) != null) {
list.get(i).Existence();
list.get(i).move();
}
}
}
}
public int ran(int o) {
Random r = new Random();
return r.nextInt(o + 1);
}
}
最后创建键盘监听器的类,并加入移动指令以及启动一次玩家对象的start方法
public class Listener implements KeyListener {
Graphics g;
ArrayList<Animal> list = new ArrayList<Animal>();
int x=0;
Player p;
int time = 0;
public Listener(Graphics g) {
this.g = g;
p= new Player(600,350,1,g,list);
list.add(p);
}
public void keyTyped(KeyEvent e) {}
public void keyPressed(KeyEvent e) {
int key= e.getKeyCode();
if(key == e.VK_UP){
p.sy = -p.speed;
p.sx = 0;
p.move();
}else if(key == e.VK_DOWN){
p.sy = p.speed;
p.sx = 0;
p.move();
}else if(key ==e.VK_LEFT){
p.sx = -p.speed;
p.sy = 0;
p.move();
}else if(key ==e.VK_RIGHT){
p.sx = p.speed;
p.sy = 0;
p.move();
}
if(time==0){
time++;
p.start();
}
}
@Override
public void keyReleased(KeyEvent e) { }
}