**打飞机文字版
一、简介
还记得许多年前的春天,你我一起“打飞机”。
那就一起写个打飞机游戏吧:
**
二、HTML内容
HTML内容把需要的图片资源以相应标签格式写出即可,分为以下几部分:
-
- 背景图片
- 自己战机的图片
- 子弹的图片
- 敌机的图片
- 敌机挂了的图片
- 计算分数的位置预留
<base href="http://images.cnblogs.com/cnblogs_com/suoning/860380/" />
<div class="bg">
<div class="me-plan"></div>
<div id="play_num"></div>
<div class="bullet">
<img src="o_cartridge.png">
</div>
<div class="x">
<img class="lift" src="o_plain1.png">
<img class="die" src="o_die1.png">
</div>
<div class="x2">
<img class="lift" src="o_plain2.png">
<img class="die" src="o_die2.png">
</div>
</div>
HTML代码
思路:
1:主飞机从底层y = 1生成,左右移动
,每次左右x轴随机移动n个位置,并且移送过的地方每一个位置都会生成一个子弹,并发射。如果此位置Y轴正好有小飞机,则击落一架且一次只能击落,加一分。(击落多架除非下一次随机位置还在原地)
三、CSS布局
CSS代码块只需把HTML代码块的图片进程简单布局,分以下几部分:
-
- 背景图片的宽与高、居中、边框、超出边界隐藏、relative相对定位
- 自己战机的宽与高、absolute相对父级定位与z-index优先级最高
- 自己战机默认隐藏,游戏开始则滑出
- 子弹、敌机的absolute相对父级定位
- 子弹、敌机的默认隐藏,游戏开始则通过克隆展示
- 敌机死亡的图片定位与隐藏
- 分数的字体大小设置及定位
<base href="http://images.cnblogs.com/cnblogs_com/suoning/860380/" />
<style>
.bg {
background-image: url("o_bg.jpg");
height: 500px;
width: 300px;
position: relative;
margin-left: 40%;
margin-top: 5%;
overflow: hidden;
border: 1px;
}
.me-plan {
width: 99px;
height: 112px;
background-image: url("o_me.png");
position: absolute;
top: 80%;
left: 35%;
display: none;
z-index: 666;
}
.bullet {
position: absolute;
display: none;
left: -10px;
}
.x, .x2 {
position: absolute;
display: none;
}
.lift {
position: absolute;
top: -110px;
}
.die {
display: none;
}
#play_num {
font-size: 30px;
}
</style>
CSS代码
2:小飞机到底层时消失,即y = 0时候消失。(这个条件暂时没用)
四、jQuery 代码块
JavaScript基础知识戳这,DOM相关戳这,jQuery全套戳这
jQuery代码块是程序的主要实现部分:
-
- 自己战机得需要跟着鼠标移动
- 自己战机移动的同时子弹也需要同时做相对定位的移动
- 敌机随机从上到下移动
- 敌机若与子弹相碰,则炸毁,相应分数增加
3:小飞机从顶层y = 10水平位置生成,x位置随机,每次随机生成三个
1、程序所需值与预定义
程序在一开始就必须获取相应的值,以便之后调用:
背景的宽与高 :判断自己战机是否超出边界,如果超出则固定在边界内某一块;
自己战机的宽与高:也做超出边界固定的作用,加上这个值更精确;
背景图片相对父元素的距离:这个值也可以说背景图片相对body的距离,因为需要不断获取鼠标的坐标,来确定自己战机的位置,鼠标的坐标减去这个值即是元素相对父级元素的距离;
还需要预定义一些值:
play_num:游戏的得分,默认定位0;
FD = {}:定义一个”字典”,存放每个敌机的对象与对于标签,用于判断碰撞。
var dwidth = $('.bg').width(); // 背景的宽与高
var dheight = $('.bg').height();
var fwidth = $('.me-plan').width(); // 自己战机的宽与高
var fheight = $('.me-plan').height();
var zwidth = $('.bullet').width(); // 子弹的宽与高
var zheight = $('.bullet').height();
var t = $('.bg').offset().top; // 背景相对父元素的距离
var l = $('.bg').offset().left;
var FD = {}; // 存放敌的的对象,封装坐标及标签
var play_num = 0; // 计算分数
4:主飞机本身长度y=1。当主飞机和小飞机下一个坐标都为(x,1)时,碰撞。游戏结束。
2、鼠标移动事件
自己战机需要不断跟着鼠标走,所有必须定义鼠标移动事件;
event.clientX与event.clientY分别为鼠标的x和y轴距离;
判断如果超出边界,则战机固定位置;
鼠标位置坐相应处理就是战机的位置(实时)。
$(".me-plan").mousemove(function m(event) {
/*
鼠标移动事件
*/
var x = event.clientX - fwidth / 2;
var y = event.clientY - fheight / 2;
MovePlanM(x - l, y - t);
})
function MovePlanM(x, y) {
/*
战机随鼠标移动
*/
if (x >= dwidth) {
x = dwidth - fwidth;
} else if (y >= dheight) {
y = dheight - fheight;
}
$('.me-plan').css({
"top": y + "px",
"left": x + "px",
});
}
3、随机值
每次敌机出现的x轴位置是不同的,所有需要写一个随机数函数;
可以以做为出现敌机的类型,小飞机与大飞机。
function Randmon() {
/*
用于随机生成x轴与敌机型号
*/
var num_one = Math.random();
var num_two = num_one * 100;
if (num_two < 80) {
num_two += 100;
}
num_stree = Math.round(Math.abs(num_two));
return num_stree
}
之前版本运行完成会发现如下一个bug:小飞机生成因为是随机的,所以可能随机生成n个,其中有
n=<1个飞机位置会重复,所以会出现以下现象 :
4、敌机类
一次可以出现一个以上敌机,而敌机属性都类似,所有需要写一个类;
三个参数,分别为x轴,y轴,还有敌机的类型;
通过克隆再插入对应标签实现多个敌机;
通过定时器使y轴自加,使敌机不断向下移动;
判断如果超出背景,则停止定时器,删除对应标签;
把对象都加入FD字典中;
注意:定时器为单独函数,不属于类,所以需要用到继承。
function FoePlan(x, y, BB) {
/*
克隆及移动敌机
*/
this.x = x;
this.y = y;
this.BB = BB;
this.Clone = function () {
var objj = $(this.BB).first().clone(true).appendTo(".bg").css("display", "block");
var s2 = setInterval(MovePlanFirst, 100);
function MovePlanFirst() {
FoePlan.call(this, x, y, BB); // 类的继承
var dic = [this.x, this.y, objj];
FD[this] = dic;
RemovePlan(this.y, s2, objj);
y += 20;
objj.css({
"top": this.y + "px",
"left": this.x + "px",
})
}
}
}
function RemovePlan(y, s2, objj) {
/*
用于删除出镜的敌机
*/
if (y > 600) {
clearInterval(s2);
$(objj).remove();
}
}
只发射了6个炮弹,却在水平方向打掉了十多个飞机,这是因为生成飞机重复了,甚至有三四个飞机随机生成在一个y
= 10的水平位置上。
5、子弹相关
两个参数,分别为自己战机x轴与y轴坐标,用于跟着战机相对移动;
定时器让y轴坐标自减,对应的子弹会一直上升;
子弹超出边界则删除定时器与对应标签;
循环读取FD字典,得到每个敌机的坐标,判断碰撞则爆炸效果,并淡出;
如果击落敌机对应分数增加;
击落敌机删除对应标签与FD中的值。
function MoveBullet(x, y) {
/*
克隆及移动子弹、判断子弹是否射到敌机
*/
var obj = $('.bullet').first().clone(true).appendTo(".bg").css("display", "block");
var s1 = setInterval(function () {
for (var item in FD) { // 判断子弹是否射到敌机
var xx = FD[item][0];
var yy = FD[item][1];
var objj = FD[item][2];
var flag = false;
if ((xx < x) && (x < (xx + 60)) && (yy < y) && ( y < (yy + 60))) {
$(objj).children().first().css("display", "none");
$(objj).children().last().css("display", "block").fadeOut("1600").fadeTo("slow", 0);
play_num += 10;
$('#play_num').text(play_num);
}
if (flag) {
$(objj).remove();
flag = false;
}
}
RemoveBullet(y, s1, obj);
y -= 20;
obj.css({
"top": (y) + "px",
"left": x + "px",
})
}, 100);
}
function RemoveBullet(y, s1, obj) {
/*
删除超出边界的子弹
*/
if (y < 0) {
clearInterval(s1);
$(obj).remove();
}
}
问题的BUG已经完善,加一个小飞机刷出条件不重叠。
6、运行程序
页面加载完成则开始运行游戏;
定时器获取自己战机的坐标,并传给子弹,让子弹不断开炮;
定时器获取随机值,并传给敌机类,让敌机不断涌现。
$(function () {
/*
页面加载完成初始化开始游戏
*/
$(".me-plan").slideDown("900");
setInterval(function () {
var x = $(".me-plan").position().left + fwidth / 2;
var y = $(".me-plan").position().top;
MoveBullet(x, y);
}, 200);
setInterval(function () {
var n = Randmon();
if (n > 130) {
var shape = '.x';
} else {
var shape = '.x2';
}
var obj = new FoePlan(n, 0, shape);
obj.Clone();
}, 1500);
});
代码如下:
五、完整代码
注:访问代码里图片路径需加前缀:
http://images.cnblogs.com/cnblogs_com/suoning/860380/ + 图片名字
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>外挂版打飞机 Nick Suo</title>
<base href="http://images.cnblogs.com/cnblogs_com/suoning/860380/"/>
<style>
.bg {
background-image: url("o_bg.jpg");
height: 500px;
width: 300px;
position: relative;
margin-left: 40%;
margin-top: 5%;
overflow: hidden;
border: 1px;
}
.me-plan {
width: 99px;
height: 112px;
background-image: url("o_me.png");
position: absolute;
top: 80%;
left: 35%;
display: none;
z-index: 666;
}
.bullet {
position: absolute;
display: none;
left: -10px;
}
.x, .x2 {
position: absolute;
display: none;
}
.lift {
position: absolute;
top: -110px;
}
.die {
display: none;
}
#play_num {
font-size: 30px;
}
</style>
</head>
<body>
<div class="bg">
<div class="me-plan"></div>
<div id="play_num"></div>
<div class="bullet">
<img src="o_cartridge.png">
</div>
<div class="x">
<img class="lift" src="o_plain1.png">
<img class="die" src="o_die1.png">
</div>
<div class="x2">
<img class="lift" src="o_plain2.png">
<img class="die" src="o_die2.png">
</div>
</div>
<script src="../jquery-1.12.4.js"></script>
<script>
/*
build time: Jul 28,2016 23:59
author: Nick Suo
email: 630571017@qq.com
*/
var dwidth = $('.bg').width(); // 背景的宽与高
var dheight = $('.bg').height();
var fwidth = $('.me-plan').width(); // 自己战机的宽与高
var fheight = $('.me-plan').height();
var zwidth = $('.bullet').width(); // 子弹的宽与高
var zheight = $('.bullet').height();
var t = $('.bg').offset().top; // 背景相对父元素的距离
var l = $('.bg').offset().left;
var FD = {}; // 存放敌的的对象,封装坐标及标签
var play_num = 0; // 计算分数
$(".me-plan").mousemove(function m(event) {
/*
鼠标移动事件
*/
var x = event.clientX - fwidth / 2;
var y = event.clientY - fheight / 2;
MovePlanM(x - l, y - t);
})
function MovePlanM(x, y) {
/*
战机随鼠标移动
*/
if (x >= dwidth) {
x = dwidth - fwidth;
} else if (y >= dheight) {
y = dheight - fheight;
}
$('.me-plan').css({
"top": y + "px",
"left": x + "px",
});
}
$(function () {
/*
页面加载完成初始化开始游戏
*/
$(".me-plan").slideDown("900");
setInterval(function () {
var x = $(".me-plan").position().left + fwidth / 2;
var y = $(".me-plan").position().top;
MoveBullet(x, y);
}, 200);
setInterval(function () {
var n = Randmon();
if (n > 130) {
var shape = '.x';
} else {
var shape = '.x2';
}
var obj = new FoePlan(n, 0, shape);
obj.Clone();
}, 1500);
});
function MoveBullet(x, y) {
/*
克隆及移动子弹、判断子弹是否射到敌机
*/
var obj = $('.bullet').first().clone(true).appendTo(".bg").css("display", "block");
var s1 = setInterval(function () {
for (var item in FD) { // 判断子弹是否射到敌机
var xx = FD[item][0];
var yy = FD[item][1];
var objj = FD[item][2];
var flag = false;
if ((xx < x) && (x < (xx + 60)) && (yy < y) && ( y < (yy + 60))) {
$(objj).children().first().css("display", "none");
$(objj).children().last().css("display", "block").fadeOut("1600").fadeTo("slow", 0);
play_num += 10;
$('#play_num').text(play_num);
}
if (flag) {
$(objj).remove();
flag = false;
}
}
RemoveBullet(y, s1, obj);
y -= 20;
obj.css({
"top": (y) + "px",
"left": x + "px",
})
}, 100);
}
function RemoveBullet(y, s1, obj) {
/*
删除超出边界的子弹
*/
if (y < 0) {
clearInterval(s1);
$(obj).remove();
}
}
function FoePlan(x, y, BB) {
/*
克隆及移动敌机
*/
this.x = x;
this.y = y;
this.BB = BB;
this.Clone = function () {
var objj = $(this.BB).first().clone(true).appendTo(".bg").css("display", "block");
var s2 = setInterval(MovePlanFirst, 100);
function MovePlanFirst() {
FoePlan.call(this, x, y, BB); // 类的继承
var dic = [this.x, this.y, objj];
FD[this] = dic;
RemovePlan(this.y, s2, objj);
y += 20;
objj.css({
"top": this.y + "px",
"left": this.x + "px",
})
}
}
}
function RemovePlan(y, s2, objj) {
/*
用于删除出镜的敌机
*/
if (y > 600) {
clearInterval(s2);
$(objj).remove();
}
}
function Randmon() {
/*
用于随机生成x轴与敌机型号
*/
var num_one = Math.random();
var num_two = num_one * 100;
if (num_two < 80) {
num_two += 100;
}
num_stree = Math.round(Math.abs(num_two));
return num_stree
}
</script>
</body>
</html>
View Code
持续更新中…
import random as r
import sys
legal_x = [0,10]
legal_y = [0,25]
class Big:
def __init__(self):
"""在y=1随机生成炮台位置"""
self.x = r.randint(0,10)
self.y = 1
def move(self):
self.Interval = []
"""随机移动左右方向并移动到新的位置(x,1)"""
self.step = r.randint(0,legal_x[1])
self.direction = r.randint(-1,1)#方向,-1为左,0不移动,1为右
new_x = self.x + self.direction * self.step
mew_y = self.y
"""判断是否越界"""
if new_x > legal_x[1]:
pos_x = legal_x[1] - (new_x - legal_x[1])
pos_y = mew_y
elif new_x < legal_x[0]:
pos_x = legal_x[0] - new_x
pos_y = mew_y
else:
pos_x = new_x
pos_y = mew_y
"""炮台移动前后对应坐标"""
if self.x > pos_x:
for i in range(pos_x,self.x + 1 ):
self.Interval.append(i)
print("炮台从坐标x=%d移动到x=%d,沿途轰了%d炮"%(self.x,pos_x,self.x + 1 -pos_x ))
print(">>>轰出%d个炮的位置是x ="% (self.x + 1 -pos_x),end = "")
print(self.Interval)
elif self.x < pos_x:
for i in range(self.x,pos_x + 1):
self.Interval.append(i)
print("炮台从坐标x=%d移动到x=%d,沿途轰了%d炮"%(self.x,pos_x,pos_x + 1 -self.x ))
print(">>>轰出%d个炮的位置是x ="% (pos_x + 1 -self.x),end = "")
print(self.Interval)
else:
self.Interval.append(pos_x)
print(">>>炮台原地轰了一炮")
print(">>>轰炮的坐标是x = %s"% str(self.Interval))
"""初始化炮台到移动的目标"""
self.x = pos_x
self.y = pos_y
return (pos_x,pos_y)
class Small:
def __init__(self):
"""在y=25随机生成小飞机位置"""
self.x = r.randint(0,legal_x[1])
self.y = legal_y[1]
def move(self):
"""固定移动,每次向下一步"""
new_x = self.x
mew_y = self.y - 1
"""判断是否越界"""
if mew_y <= legal_y[0]:
self.x = r.randint(0,legal_x[1])
self.y = legal_y[1]
else:
self.x = new_x
self.y = mew_y
return (new_x , mew_y)
class Boom:
"""核武器"""
def __init__(self):
self.x = r.randint(0,legal_x[1])
self.y = 1
def DAFEIJI(n):
Scorer = 0
list_s = []
big_air = Big()
"""激光炮台出场"""
i = r.randint(9,10)
while n:
list_pos = []
boom = Boom()
"""核武器生成"""
for numbers in range(1 ,i + 1):
small_air = Small()#小飞机出场数量位置随机,设置不重叠
if small_air.x not in list_pos:
list_pos.append(small_air.x)
list_s.append(small_air)
else:
continue
pos = big_air.move()
n = n - 1
if pos != (boom.x ,boom.y):
for each in list_s[:]:
pos_small = each.move()
if pos == pos_small:
print(">>>>>>>很不幸! 您的炮台撞小飞机了....GG!!")#这个几率.....
print("本次打飞机的分数是:%d" % Scorer)
sys.exit(0)
elif pos_small[0] in (big_air.Interval):
"""一条直线打的,其实是激光炮"""
print("一架小飞机被打掉..")
Scorer += 1
list_s.remove(each)
else:
print("炮台加载了核武器...======================清屏!=======================..")
Scorer += len(list_s)
list_s.clear()
print("本次打飞机的分数是:%d" % Scorer)
#==============================主程序==================================
DAFEIJI(5)
初始界面y值越大,游戏结束几率越小。
想了解更多Python知识或者想与更多的朋友一起学习交流,可以加群705673780,群文件内更多免费资料可供学习哦~