【flash基础】简单的 打飞机小游戏
学校还教这东西,也真是迷。比起 普通的游戏库 应该舒服的多。
纯当练手写了一个demon。很简陋,不过 代码量很少应该比较好参考。
网上的资料不是很多,有兴趣的可以拿去参考下。
代码
链接:https://pan.baidu.com/s/1Vx_A37a07qJIkg443N3Jwg
提取码:opi9
--------------------------效果---------------------------
--------------------------需求---------------------------
先分析一下我们需要什么。
小炮塔
1.可以被wasd控制 【事件绑定】
2.炮塔会跟着鼠标转 【坐标转向量转角度】
3.点击鼠标会发射炮弹 【事件绑定 和 new出来子弹】
敌人
1.被击中的时候会消失 【碰撞检测】
子弹
1会沿着一个方向一直飞 【坐标转单位向量*速度】
2 击中敌人会消失 【碰撞检测】
主循环
最重要的 游戏是运行在一个主循环里面的 我们需要去创造一个主循环。
--------------------------类的介绍---------------------------
几个类 以下的类都实现了以上的功能
bullet是子弹
enamy是敌人
Gloablinput 用来接收输入的。比如你输入w 的forward就会变成1
鼠标点击 里面一个布尔类型的变量就会变true
Mycharacter 是自机。
--------------------------代码---------------------------
第一帧 主要是一些变量的初始化。很对应的 事件回调函数的绑定。
allObjList数组
包含舞台上所有的游戏对象。
所有的游戏对象都会有一个Tick()方法。这个数组是用来执行这个方法的。
这个tick方法很很重要,可以认为 他是一个对象的主函数,用于 对象参与到游戏循环检测。
enemy_list 和 bullet_list
用于子弹和敌人的碰撞检测用。
"第一帧"
import GlobalInput
import Math
GlobalInput.Right = 0
GlobalInput.Forward = 0
GlobalInput.mouseDown = false
//1 变量初始化
//2 事件处理函数
//3 按钮绑定
//12-14 游戏主循环
//监听处理各种输入
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
stage.addEventListener(MouseEvent.MOUSE_UP,mouseUpHandler);
var allObjList:Array = new Array() //Tick方法调用
var enemy_list:Array = new Array() //方便碰撞检测
var bullet_list:Array = new Array() //子弹产生就放进去
var self_char = new Mycharacter(this,new mychar1())
allObjList.push(self_char)
var i,j,k
for (i=0;i<20;i++) //创造敌人
{
j = new Enamy(this,Math.random()*550+1,Math.random()*400+1)
enemy_list.push(j)
allObjList.push(j)
}
第二帧
这里是绑定了 上下左右 和 鼠标点击的输入。
值得一提的是
当按下 左 的时候 GlobalInput.Right =1
按下 右 的时候 GlobalInput.Right =-1
这里假设了右边是正方向。因为物体移动的时候 实际上就是坐标在变化。
右边移动的时候是
对象.x+=speed
左边移动的时候
对象.x-=speed
我这里规定了右边是正方向因此。对象的左右移动
对象.x+= speed * GlobalInput.Right 也就是 速度*方向
"第二帧"
function keyDownHandler(e:KeyboardEvent):void
{
switch(e.keyCode)
{
case "W".charCodeAt():
case Keyboard.UP:
GlobalInput.Forward =-1
break;
case "S".charCodeAt():
case Keyboard.DOWN:
GlobalInput.Forward = 1;
break;
case "A".charCodeAt():
case Keyboard.LEFT:
GlobalInput.Right = -1;
break;
case "D".charCodeAt():
case Keyboard.RIGHT:
GlobalInput.Right = 1;
break;
}
}
function keyUpHandler(e:KeyboardEvent):void
{
switch(e.keyCode)
{
case "W".charCodeAt():
case Keyboard.UP:
case "S".charCodeAt():
case Keyboard.DOWN:
GlobalInput.Forward = 0;
break;
case "A".charCodeAt():
case Keyboard.LEFT:
case "D".charCodeAt():
case Keyboard.RIGHT:
GlobalInput.Right = 0;
break
}
}
function mouseDownHandler(e:MouseEvent):void
{
GlobalInput.mouseDown = true;
}
function mouseUpHandler(e:MouseEvent):void
{
GlobalInput.mouseDown = false;
}
第3帧 写了个按钮的 不是很重要
显示按钮界面 并且吧游戏暂停在这里。
bt1.addEventListener(MouseEvent.CLICK, bt1Action);
bt2.addEventListener(MouseEvent.CLICK, bt2Action);
function bt1Action (event:MouseEvent)
{
gotoAndPlay(4)
}
function bt2Action(event:MouseEvent):void
{ var url = "https://www.bilibili.com/"
navigateToURL(new URLRequest(url), "_blank");
}
stop()
游戏主循环部分
gotoAndPlay(11) 表示从第11帧执行,可以看出来游戏 一直在执行第12帧的代码。
再次说下 Tick方法
他是每一个参与游戏的物体都会有的一个函数,游戏循环的时候 每一个参与游戏互动的对象都会执行他。所以 看一个类的时候 去看Tick就行了。
你可以把它当成是一个接口函数,只是代码量太少我没写。
for each (i in allObjList)
i.Tick()
//鼠标按下 调用 炮台的attack方法
//attck方法会返回一个子弹对象 或者是一个假 这里主要是吧生成的子弹存数组
if (GlobalInput.mouseDown){
j = self_char.attack()
if (j){ //武器未冷却的时候 会返回一个假
allObjList.push(j)
bullet_list.push(j)
}
}
//碰撞检测 让所有的子弹i 和 所有的敌人j 进行碰撞检测
//如果返回 true 就执行 对敌人的伤害
for each(i in bullet_list)
for each (j in enemy_list)
if (i.drawObject.hitTestObject(j))
j.applyDamage(300)
gotoAndPlay(11)
----------------------------------类--------------------------------------
好了 开始说类。
重要的事情说3次
注意Tick函数
炮台类
move 函数的if 条件 主要是一些边界检测。没写完 就用true代替
移动的逻辑
drawObject.x = 速度 * 方向
这一行很重要 相关的数学算法 让炮台会跟着鼠标转
drawObject.rotation = Math.atan2(vector[1],vector[0]) * 180/Math.PI -90
首先 可以获得的是 鼠标坐标 和 炮台坐标,获得一个向量vector。指向鼠标的向量。
用 Math.atan()函数 获得他的 弧度。
弧度* 180/Math.PI 转化为角度
至于那个-90 emmm 我也不清楚。可能是坐标轴的原因吧。gui程序的坐标轴是 这样子的。 我-90度 他就对了。
O→ X
↓
Y
attack函数
打炮low,new子弹。
这里 又用到了 前面说的那个向量了。 【鼠标坐标-炮塔坐标】
这个向量决定了 子弹的飞行方向,当然 new 子弹的时候一定要传参给他。
当然 这里 有个攻击间隔时间。
攻击一次 攻击timer 变为4。Tick 函数 攻击timer-1
只有小于0的时候才攻击
package {
import Math
public class Mycharacter {
public var speed:int = 10 //速度
public var drawObject; //影片剪辑 就是那个炮台长什么样子
var attackTime = 10 //攻击计时器
var attack_interval = 4 //攻击的间隔时间
var stage
public function Mycharacter(_stage,actor) {
this.stage = _stage
drawObject = actor
drawObject.y = 200
drawObject.x = 200
// constructor code
}
public function attack(){
if (attackTime<0){
var v:Array = [drawObject.x-stage.mouseX+drawObject.width/2,drawObject.y-stage.mouseY+drawObject.height/2]
attackTime=attack_interval
return new bullet(this.stage,this, new bullet_image(),v)
}
else
return false
}
public function move(){
if ( true && GlobalInput.Right>0)
drawObject.x += speed * GlobalInput.Right
if ( drawObject.x > 0 && GlobalInput.Right<0)
drawObject.x += speed * GlobalInput.Right
if ( true && GlobalInput.Forward >0)
drawObject.y += speed * GlobalInput.Forward
if ( drawObject.y > 0 && GlobalInput.Forward <0)
drawObject.y += speed * GlobalInput.Forward
var vector:Array = [drawObject.x-stage.mouseX+drawObject.width/2,drawObject.y-stage.mouseY+drawObject.height/2]
//trace(Math.atan2(vector[0],vector[1]) * 180/Math.PI)
drawObject.rotation = Math.atan2(vector[1],vector[0]) * 180/Math.PI -90 //这里可能是坐标轴的问题
//我所熟悉的坐标右手为x 这里 乱 感觉在强行解释
stage.addChild(drawObject)
}
public function Tick(){
this.attackTime -=1
move()
}
}
}
敌人类
敌人生命的 被击中的时候会调用 applydamage 这里没有多写而已。做出游戏这里是用的到的。
move 函数也是 敌人一定有他自己的移动逻辑。移动的时候 必须检测下 是否还活着,死了记得销毁对象。
这里 写的是 假销毁
this.x = -1000 this.y = -1000 移动到舞台外面就没了嘛。
package {
public class Enamy extends EnemyImage {
public var _stage
public var healthy = 100
public var is_live = true
public function Enamy(_stage,x,y) {
// constructor code
this._stage = _stage
this.x = x
this.y = y
}
public function move()
{
if (healthy>0)
_stage.addChild(this)
else if (this.is_live)
{
this.x = -1000
this.y = -1000
}
}
public function Tick(){
move()
}
public function applyDamage(num)
{
this.healthy -= num
}
}
}
子弹类
构造函数在做这件事
速度 = 速率* 单位化的方向向量
顺便获取 发射者的位置
package {
import Math
public class bullet {
public var speed = 10
public var vector:Array = [0,0]
public var drawObject;
var stage
public function bullet(_stage,launcher,image,v) {
stage = _stage
vector[0] = v[0] / Math.sqrt(v[0]*v[0]+v[1]*v[1])
vector[1] = v[1] / Math.sqrt(v[0]*v[0]+v[1]*v[1])
drawObject = image
drawObject.x = launcher.drawObject.x
drawObject.y = launcher.drawObject.y
//drawObject.x = launcher.drawObject.x + launcher.drawObject.width/2
//drawObject.y = launcher.drawObject.y + launcher.drawObject.height/2
// constructor code
}
public function setSpeed(sp)
{
speed = sp
}
public function move(){
drawObject.x -= vector[0] *speed
drawObject.y -= vector[1] *speed
stage.addChild(drawObject)
}
public function Tick(){
move()
}
}
}
游戏的话 自机 是需要和 敌人和子弹做碰撞检测的。
希望对大家有帮助。
推荐阅读
-
【flash基础】简单的 打飞机小游戏
-
一个简单的自动发送邮件系统(二)_php基础
-
cakephp setFlash()及flash()方法都不起作用,setFlash()的具体用法及简单案例,该如何处理
-
一个简单实现多条件查询的例子_php基础
-
一个简单的自动发送邮件系统(一)_php基础
-
CSS基础学习-简单的CSS语句
-
Unity3D笔记---简单的捕鱼小游戏
-
用pygame实现一个简单的垃圾分类小游戏(已获校级二等奖)
-
Unity 基础 之 实现简单的Android移动端本地数据读取与写入封装(简单加密写入,解密读取 json 数据)
-
cakephp setFlash()及flash()方法都不起作用,setFlash()的具体用法及简单案例,该如何处理