苹果打飞机游戏,敌人死后子弹穿过苹果可以吃

你不会以为所有打飞机游戏只需要躲躲子弹就能过关吧?-ZAKER新闻
总去街机厅的人应该知道。除了格斗、音游之外,还有一些常年霸占街机区的游戏类型,就是 " 打飞机 "。最起码街机厅都有那么一两台,一般都是 " 彩京系列 " 作品。秉承着 " 死得快 "、" 玩着爽 " 的观念,游戏厅老板看着你一个钢镚只能玩两三分钟,不知道心里乐成什么样儿。既然聊到了飞行射击游戏(以下简称 STG),那看这篇文章的你不妨回忆一下,此时此刻你脑中浮现的 " 打飞机 " 游戏都有哪些。我想应该有这个《铁板阵》这个《小蜜蜂》或者这个《沙罗曼蛇》时代不同啦!这些老掉牙的古董还拿出去和朋友炫耀,只能让人说你是一个食古不化,冥顽不灵的老家伙。现在连小朋友都知道《雷霆战机》,虽然有点过气了,但火的那阵也没少刷屏朋友圈秀分数。至少你也要拿出这个《雷电》《打击者 1945》《怒首领蜂》才算跟得上时代潮流。不管怎么说,这类游戏总给人一个感觉,就是看起来很难。看似让人眼花缭乱的弹幕,用大触们的话说 " 扭一扭就过去了 ",说的轻松,还不是因为自身中弹判定小嘛!后来人们发现这样玩远比传统射击游戏擦到就死来得更极限、更刺激。就把中弹判定弄得越来越小,然后敌人子弹的密度变得越来越大。比较具有代表性的就是前面提到的 "《怒首领蜂》系列",还有几乎不用我说你们就能猜到的 "《东方》系列"。华丽的弹幕和摄人心魄的 BGM,还有发生在架空世界观的奇幻故事。哎!可谓是此生无悔入东方,来生……打住!可能要让你失望了,这篇文章并不会跪舔神主 ZUN 和幻想乡众妹子。而要介绍一款虽然小众,但只要知道的人无不称奇的 STG 神作——《斑鸠》。介绍游戏之前,先来放个地址:http://store.steampowered.com/app/253750/本来 2014 年就上架 steam 了,但一直未定价,所以没开卖。目前可以购买了,36 软妹币,虽然价格并不是很高,但还是建议您看完这篇文章之后再决定买不买。虽然上架 steam 没几年,但《斑鸠》其实是一款发行接近 10 年的老游戏了。最早登陆的是世嘉的DC(Dreamcast)和街机平台。工作室是大名鼎鼎的 Treasure,基本上是世嘉御用工作室。脍炙人口的 MD 格斗神作《幽游白书:魔强统一战》就出自其手。《幽游白书:魔强统一战》《斑鸠》开发组一共只有 3 人。讲道理,如今不少独立游戏神作都是由三两个人的小组研发的。甚至还有像《洞窟物语》这样独自一人完成的,包括程序、音乐、美术等一切工作。虽然是近乎于 10 年之前的游戏了,但是《斑鸠》在画面和特效上绝不输于其他作品游戏项目组不在乎人多少,而是这些人都能做什么。Hiroshi Iuchi其一人兼顾游戏策划、平面设计和音乐创作,这一般人可是很难做到的。回头再来说说世嘉,这是一个很暴露年龄的游戏公司。可以说,在 2000 年以后,世嘉主机几乎再没有什么大的建树,也逐渐淡出了玩家视线。DC(Dreamcast)剩下的就是如今我们常看到的 " 索狗、任豚 " 了,不过有趣君并不想陷入这种无谓的互黑中,毕竟我们聊的是世嘉嘛。玩过世嘉游戏的人应该都能感受得到,这是一个把主机硬生生做成街机的公司。MD 版《格斗四人组》当年效果堪比街机简单来讲就是不管什么游戏,几乎只有一个难度,而且这个难度有时候在现在看来非常不合理。如今的电子游戏,开发商几乎都把玩家当成小宝宝。" 哎呀!宝宝这游戏太难了!那我们来降低难度吧!"" 哎呀!又太简单了?没事,你看咱们这里有非常具有挑战性的 MODE 哦!"世嘉就不惯病,爱玩不玩,反正你可能手残一辈子都看不到最后 BOSS,但这游戏就这么设计的,你不想花时间就是没法通关!MD(MEGA DRIVE)的《魂斗罗》,其难度十分鬼畜只能说,这与当时的主流游戏观点相同,如果按照目前 " 索任 " 互黑的程度来看,在世嘉游戏面前论游戏性,大家都不用聊了。稍微有些跑题,我们还是回来说《斑鸠》吧!这是一个非常另类且极度困难甚至能把人逼疯的 STG。应该算是硬核 STG 的代表作,而且是巅峰之作。有句话怎么说的?" 流行的不一定经典,经典一定流行。"这句话放在《斑鸠》上,我就觉得不太合适。难度注定了它流行不起来,但新颖的创意却又让它成为了经典。《魔兽世界》" 十字军试炼 - 瓦格里双子 "BOSS 的设计思路正来源于《斑鸠》说到这儿估计看官们会有点不耐烦了。" 你一直说《斑鸠》神作,到底神在哪了?和《东方》、《怒首领蜂》比起来到底孰优孰劣?"客观点说,它们没什么可比性。其一,无论是弹幕游戏也好,传统 STG 也罢,它们都有一个共同的特征——生存第一。STG 高端玩家生存就是一切,不管什么 STG,躲开敌人的子弹是最优先级,无论你有多么渴望分数。所以一般情况下,玩家的视线大多集中在自机周围很小的一部分上。图中,白色为自身判定,一般玩家视线会集中在红色区域,少数玩家能做到集中在黄色区域当然一些关卡也需要一些大范围位移,但不多见。如黄色箭头所示,每一作东方正作都会在下方提示 BOSS 当前位置以便观看所以在设计这些游戏的时候,设计师也会更多地把精力放在敌机的弹幕上,自机的子弹设计相对次要。无非就是吃 "P",然后自机火力越来越强,最后变得特别夸张。实在不行一个 "BOMB" 清屏,继续躲。可《斑鸠》就完全不走寻常路。游戏中所有的子弹和敌人,包括你自己都是由黑白两色构成的。白色的敌人释放白色子弹,黑色敌人释放黑色子弹。自机可以在两色之间切换。同理,同色的子弹撞到同色的自机并不会坠毁,反而会增加你的能量。只有不同颜色的子弹击中你才会死亡。可能 STG 大神会觉得 " 这就相当于刨去了一半的弹幕量,躲起来相对会简单的啊!"试试就知道,根本不是一回事儿。当两种颜色的弹幕穿插出现时,你就会产生一种混乱感。因为出现了除躲避的第二种选择。而且自机的子弹永远都不会增强,在面对同色敌人的时候,伤害很低,只有切换成不同颜色才有更强的火力。高风险高回报,还是低风险低回报,由玩家自己做选择。玩家的视线将不仅仅局限于自机周围的一小块,而是要纵观全屏,看每种颜色弹幕的轨迹,判断是应该迎面直撞,还是紧急躲避。其二,奖励机制。一般来讲,STG 游戏的奖励机制一般就是杀死敌人或者吃到奖励道具。反正就是无脑按着开枪键,在躲开弹幕的前提下去尽可能多地刷分数。一些不想刷分,一门心思想 " 混关 " 的手残党则直接将奖励道具从视线中屏蔽。遇事不决一个 "B",毕竟 " 抱 B 死 " 是新手最常犯的失误。据说上来连放 3B 可以避免此现象发生而《斑鸠》,不仅没有 "BOMB" 的设定,而且在奖励分数这块儿加入了一个很奇葩的设定——连击。连续击败同颜色的敌机 3 次,就会获得一个分数加成,连续获得分数加成能提高奖励倍数。当然,中间一旦中断,就只有从 1 层重新开始了。游戏中也没有任何奖励道具,一切分数都是通过击毁敌机获得。更没有 " 加残 " 道具,想要续命,就必须达到指定分数。敌机的出现也是黑白两色穿插的,何时射击,何时停手,都需要玩家不断磨练技艺并从中一点点摸索。想拿高分,除了背版,别无它法。从此你就能看出来,一个高手和一个初探者的差距简直就如同天地。其三,难度设定大多 STG 游戏想要提升或降低游戏难度都会在增减弹幕上做文章。还拿我大《东方》举例,从 E 到 L 难度,BOSS 符卡的变化异常明显。而道中的小怪就更不必提了,E 难度几乎不需要怎么躲,而 L 难度从最开始就给你很大的压力。再来看看《斑鸠》。有趣君不得不承认,《斑鸠》的难度设定应该是最猎奇的。在理解难度之前,你需要先理解 " 返弹 " 这个概念。就是在击毁敌机之后会有子弹从敌机飞出来。彩京在旗下作品的 2 周目中非常频繁地使用 " 反弹 "。《斑鸠》的难度设定是:简单难度下,敌机没有反弹。普通难度下,同色敌机有反弹。困难难度下,所有敌机有反弹。每个难度并不是一个逐渐增加躲避难度的线性曲线,而是几乎换了另外一个游戏。是否反弹,如何反弹直接影响了你切换颜色的节奏。简直丧心病狂。好了,你也看到了,《斑鸠》的确是一个另类,对吧。很佩服开发者的脑洞和敢于创新的勇气。可事实是,《斑鸠》给人的挫败感几乎比任何一个核心向 STG 都强。玩个几十把连第三关都到不了的情况太常见了。所以这就是前面为何让你在买之前先看文章的原因。也是为了防止不怎么买游戏的你无辜喜 +1 的说。那么,到底什么玩家适合玩《斑鸠》呢?可能我是一个《东方》厨,对待每款正作都游刃有余,去街机厅也经常在 " 打飞机 " 游戏中秀得飞起,那我到底能不能玩得来呢?其实这么多年的游戏生涯,有趣君也算是一个很喜欢 STG 的核心厨了。即便这样,面临《斑鸠》依然感到了心有余而力不足。我常把玩 "《东方》系列 " 的玩家分为两类,一类是爱好同人大于正作的玩家。莲妈什么的……他们只对故事或者人设感兴趣,顺便体验几个小时的正作,虐虐 "Normal",刷刷 "EX",仅此而已。另外一种是逮着一作死磕的那种,也就是所谓的 " 东方 STG" 核心玩家,总之就是花大把的时间追求极限的触手系。HARD 难度高分视频我想也只有后者面对《斑鸠》才有一战之力吧!首先得足够有耐心用来背版,再一个就是对极限的追求——那种类似于强迫症患者的追求。高桥名人虽然把《斑鸠》说得这么硬核,有点让人敬而远之。但实际上《斑鸠》的剧情还是非常富有哲学意味的。在这里就不剧透了,大家可以去游戏中自行体验。总之,就是这样一个创意和难度同样让人叹为观止的游戏被大家奉为神作。和朋友出去聊 " 打飞机 " 游戏,就说《斑鸠》,一点都不跌份儿。别怕你自己玩得不好,看似触手大神的人也不见得比你玩得好到哪儿去。Stunfest 2014 的大神双控表演你就问他一句话:" 能双控不?",一般他就 " 立正稍息 " 了。因为玩过的人都会骂一句:" 破游戏 TMD 真难啊!"加载中
相关标签:
原网页已经由 ZAKER 转码排版
手游那点事2小时前
游戏时光VGTIME2小时前
NGA玩家社区1小时前
NGA玩家社区4小时前
游戏时光VGTIME3小时前
玩加赛事1小时前
蚕豆网1小时前
玩加赛事1小时前
手游那点事2小时前
NGA玩家社区2小时前
178游戏网2小时前
任玩堂2小时前
17173VR28分钟前
空中网1小时前
空中网1小时前一款坦克打飞机的游戏,传统的玩法,要躲避敌人的子弹和导弹哦,取得最终的胜利。
复制地址:
1.按键操作
mousemove瞄准mouseleft射击AD/lr控制坦克左右移动
2.如何开始
游戏加载完毕点击屏幕进入游戏。
3.游戏目标
消灭所有敌人。
大家还喜欢
登录7k7k发现更多乐趣
7K7K网页游戏
7K7K儿童游戏
法律顾问:北京市诺恒律师事务所
京公网安备37
游戏作品版权归原作者享有,如无意之中侵犯了您的版权,请您按照来信告知,本网站将应您的要求删除。
7k7k小游戏温馨提示:适度游戏娱乐,沉迷游戏伤身,合理安排时间,享受快乐生活……Android实战打飞机游戏之子弹生成与碰撞以及爆炸效果(5)
转载 & & 作者:liudao7994
这篇文章主要为大家详细介绍了Android实战打飞机游戏之子弹生成与碰撞以及爆炸效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
Android实战打飞机游戏子弹生成,新建子弹类
public class Bullet {
// 子弹图片资源
public Bitmap bmpB
// 子弹的坐标
public int bulletX, bulletY;
// 子弹的速度
// 子弹的种类以及常量
public int bulletT
public static final int BULLET_PLAYER = -1;
public static final int BULLET_DUCK = 1;
public static final int BULLET_FLY = 2;
public static final int BULLET_BOSS = 3;
// 子弹是否超屏, 优化处理
public boolean isD
// Boss疯狂状态下子弹相关成员变量
// 当前Boss子弹方向
// 8方向常量
public static final int DIR_UP = -1;
public static final int DIR_DOWN = 2;
public static final int DIR_LEFT = 3;
public static final int DIR_RIGHT = 4;
public static final int DIR_UP_LEFT = 5;
public static final int DIR_UP_RIGHT = 6;
public static final int DIR_DOWN_LEFT = 7;
public static final int DIR_DOWN_RIGHT = 8;
// 子弹当前方向
public Bullet(Bitmap bmpBullet, int bulletX, int bulletY, int bulletType) {
this.bmpBullet = bmpB
this.bulletX = bulletX;
this.bulletY = bulletY;
this.bulletType = bulletT
// 不同的子弹类型速度不一
switch (bulletType) {
case BULLET_PLAYER:
speed = 4;
case BULLET_DUCK:
speed = 3;
case BULLET_FLY:
speed = 4;
case BULLET_BOSS:
speed = 5;
public void draw(Canvas canvas, Paint paint) {
canvas.drawBitmap(bmpBullet, bulletX, bulletY, paint);
// 子弹的逻辑
public void logic() {
// 不同的子弹类型逻辑不一
// 主角的子弹垂直向上运动
switch (bulletType) {
case BULLET_PLAYER:
bulletY -=
if (bulletY & -50) {
// 鸭子和苍蝇的子弹都是垂直下落运动
case BULLET_DUCK:
case BULLET_FLY:
bulletY +=
if (bulletY & MySurfaceView.screenH) {
case BULLET_BOSS:
// Boss疯狂状态下的子弹逻辑待实现
// 边界处理
if (bulletY & MySurfaceView.screenH || bulletY &= -40
|| bulletX & MySurfaceView.screenW || bulletX &= -40) {
在在MySurfacview里面调用 生成子弹主角的和自己的
package com.
import java.util.R
import java.util.V
import android.content.C
import android.content.res.R
import android.graphics.B
import android.graphics.BitmapF
import android.graphics.C
import android.graphics.C
import android.graphics.P
import android.view.KeyE
import android.view.MotionE
import android.view.SurfaceH
import android.view.SurfaceHolder.C
import android.view.SurfaceV
public class MySurfaceView extends SurfaceView implements Callback, Runnable {
private SurfaceH
// 1 定义游戏状态常量
public static final int GAME_MENU = 0;// 游戏菜单
public static final int GAMEING = 1;// 游戏中
public static final int GAME_WIN = 2;// 游戏胜利
public static final int GAME_LOST = 3;// 游戏失败
public static final int GAME_PAUSE = -1;// 游戏菜单
// 当前游戏状态(默认初始在游戏菜单界面)
public static int gameState = GAME_MENU;
// 声明一个Resources实例便于加载图片
private Resources res = this.getResources();
// 声明游戏需要用到的图片资源(图片声明)
private Bitmap bmpBackG// 游戏背景
private Bitmap bmpB// 爆炸效果
private Bitmap bmpBoosB// Boos爆炸效果
private Bitmap bmpB// 游戏开始按钮
private Bitmap bmpButtonP// 游戏开始按钮被点击
private Bitmap bmpEnemyD// 怪物鸭子
private Bitmap bmpEnemyF// 怪物苍蝇
private Bitmap bmpEnemyB// 怪物猪头Boos
private Bitmap bmpGameW// 游戏胜利背景
private Bitmap bmpGameL// 游戏失败背景
private Bitmap bmpP// 游戏主角飞机
private Bitmap bmpPlayerHp;// 主角飞机血量
private Bitmap bmpM// 菜单背景
public static Bitmap bmpB// 子弹
public static Bitmap bmpEnemyB// 敌机子弹
public static Bitmap bmpBossB// Boss子弹
public static int screenW;
public static int screenH;
// 声明一个敌机容器
private Vector&Enemy& vcE
// 每次生成敌机的时间(毫秒)
private int createEnemyTime = 50;
// 敌人数组:1和2表示敌机的种类,-1表示Boss
// 二维数组的每一维都是一组怪物
private int enemyArray[][] = { { 1, 2 }, { 1, 1 }, { 1, 3, 1, 2 },
{ 1, 2 }, { 2, 3 }, { 3, 1, 3 }, { 2, 2 }, { 1, 2 }, { 2, 2 },
{ 1, 3, 1, 1 }, { 2, 1 }, { 1, 3 }, { 2, 1 }, { -1 } };
// 当前取出一维数组的下标
private int enemyArrayI
// 是否出现Boss标识位
private boolean isB
// 随机库,为创建的敌机赋予随即坐标
private GameMenu gameM
private GameBg gameBg;
// 敌机子弹容器
private Vector&Bullet& vcB
// 添加子弹的计数器
private int countEnemyB
// 主角子弹容器
private Vector&Bullet& vcBulletP
// 添加子弹的计数器
private int countPlayerB
* SurfaceView初始化函数
public MySurfaceView(Context context) {
super(context);
sfh = this.getHolder();
sfh.addCallback(this);
paint = new Paint();
paint.setColor(Color.WHITE);
paint.setAntiAlias(true);
setFocusable(true);
* SurfaceView视图创建,响应此函数
public void surfaceCreated(SurfaceHolder holder) {
screenW = this.getWidth();
screenH = this.getHeight();
initGame();
// 实例线程
th = new Thread(this);
// 启动线程
th.start();
* 加载游戏资源
private void initGame() {
// 加载游戏资源
bmpBackGround = BitmapFactory
.decodeResource(res, R.drawable.background);
bmpBoom = BitmapFactory.decodeResource(res, R.drawable.boom);
bmpBoosBoom = BitmapFactory.decodeResource(res, R.drawable.boos_boom);
bmpButton = BitmapFactory.decodeResource(res, R.drawable.button);
bmpButtonPress = BitmapFactory.decodeResource(res,
R.drawable.button_press);
bmpEnemyDuck = BitmapFactory.decodeResource(res, R.drawable.enemy_duck);
bmpEnemyFly = BitmapFactory.decodeResource(res, R.drawable.enemy_fly);
bmpEnemyBoos = BitmapFactory.decodeResource(res, R.drawable.enemy_pig);
bmpGameWin = BitmapFactory.decodeResource(res, R.drawable.gamewin);
bmpGameLost = BitmapFactory.decodeResource(res, R.drawable.gamelost);
bmpPlayer = BitmapFactory.decodeResource(res, R.drawable.player);
bmpPlayerHp = BitmapFactory.decodeResource(res, R.drawable.hp);
bmpMenu = BitmapFactory.decodeResource(res, R.drawable.menu);
bmpBullet = BitmapFactory.decodeResource(res, R.drawable.bullet);
bmpEnemyBullet = BitmapFactory.decodeResource(res,
R.drawable.bullet_enemy);
bmpBossBullet = BitmapFactory
.decodeResource(res, R.drawable.boosbullet);
// 菜单类实例化
gameMenu = new GameMenu(bmpMenu, bmpButton, bmpButtonPress);
// 实例游戏背景
gameBg = new GameBg(bmpBackGround);
// 实例主角
player = new Player(bmpPlayer, bmpPlayerHp);
//敌机子弹容器实例
vcBullet = new Vector&Bullet&();
//主角子弹容器实例
vcBulletPlayer = new Vector&Bullet&();
// 实例敌机容器
vcEnemy = new Vector&Enemy&();
// 实例随机库
random = new Random();
* 游戏绘图
public void myDraw() {
canvas = sfh.lockCanvas();
if (canvas != null) {
canvas.drawColor(Color.WHITE);
// 绘图函数根据游戏状态不同进行不同绘制
switch (gameState) {
case GAME_MENU:
gameMenu.draw(canvas, paint);
case GAMEING:
gameBg.draw(canvas, paint);
player.draw(canvas, paint);
if (isBoss == false) {
// 敌机绘制
for (int i = 0; i & vcEnemy.size(); i++) {
vcEnemy.elementAt(i).draw(canvas, paint);
//敌机子弹绘制
for (int i = 0; i & vcBullet.size(); i++) {
vcBullet.elementAt(i).draw(canvas, paint);
// boss 绘制
// 处理主角子弹绘制
for (int i = 0; i & vcBulletPlayer.size(); i++) {
vcBulletPlayer.elementAt(i).draw(canvas, paint);
case GAME_WIN:
case GAME_LOST:
case GAME_PAUSE:
} catch (Exception e) {
// TODO: handle exception
} finally {
if (canvas != null)
sfh.unlockCanvasAndPost(canvas);
* 触屏事件监听
public boolean onTouchEvent(MotionEvent event) {
switch (gameState) {
case GAME_MENU:
gameMenu.onTouchEvent(event);
case GAMEING:
case GAME_WIN:
case GAME_LOST:
case GAME_PAUSE:
* 按键事件监听
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (gameState) {
case GAME_MENU:
case GAMEING:
player.onKeyDown(keyCode, event);
case GAME_WIN:
case GAME_LOST:
case GAME_PAUSE:
return super.onKeyDown(keyCode, event);
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (gameState) {
case GAME_MENU:
case GAMEING:
player.onKeyUp(keyCode, event);
case GAME_WIN:
case GAME_LOST:
case GAME_PAUSE:
return super.onKeyUp(keyCode, event);
* 游戏逻辑
private void logic() {
switch (gameState) {
case GAME_MENU:
case GAMEING:
gameBg.logic();
player.logic();
// 敌机逻辑
if (isBoss == false) {
// 敌机逻辑
for (int i = 0; i & vcEnemy.size(); i++) {
Enemy en = vcEnemy.elementAt(i);
// 因为容器不断添加敌机 ,那么对敌机isDead判定,
// 如果已死亡那么就从容器中删除,对容器起到了优化作用;
if (en.isDead) {
vcEnemy.removeElementAt(i);
en.logic();
// 生成敌机
if (count % createEnemyTime == 0) {
for (int i = 0; i & enemyArray[enemyArrayIndex]. i++) {
if (enemyArray[enemyArrayIndex][i] == 1) {
int x = random.nextInt(screenW - 100) + 50;
vcEnemy.addElement(new Enemy(bmpEnemyFly, 1, x, -50));
} else if (enemyArray[enemyArrayIndex][i] == 2) {
int y = random.nextInt(20);
vcEnemy.addElement(new Enemy(bmpEnemyDuck, 2, -50,
} else if (enemyArray[enemyArrayIndex][i] == 3) {
int y = random.nextInt(20);
vcEnemy.addElement(new Enemy(bmpEnemyDuck, 3,
screenW + 50, y));
// 这里判断下一组是否为最后一组(Boss)
if (enemyArrayIndex == enemyArray.length - 1) {
enemyArrayIndex++;
// 每2秒添加一个敌机子弹
countEnemyBullet++;
if (countEnemyBullet % 40 == 0) {
for (int i = 0; i & vcEnemy.size(); i++) {
Enemy en = vcEnemy.elementAt(i);
// 不同类型敌机不同的子弹运行轨迹
int bulletType = 0;
switch (en.type) {
case Enemy.TYPE_FLY:
bulletType = Bullet.BULLET_FLY;
case Enemy.TYPE_DUCKL:
case Enemy.TYPE_DUCKR:
bulletType = Bullet.BULLET_DUCK;
vcBullet.add(new Bullet(bmpEnemyBullet, en.x + 10,
en.y + 20, bulletType));
// 处理敌机子弹逻辑
for (int i = 0; i & vcBullet.size(); i++) {
Bullet b = vcBullet.elementAt(i);
if (b.isDead) {
vcBullet.removeElement(b);
b.logic();
//每1秒添加一个主角子弹
countPlayerBullet++;
if (countPlayerBullet % 20 == 0) {
vcBulletPlayer.add(new Bullet(bmpBullet, player.x + 15, player.y - 20, Bullet.BULLET_PLAYER));
// 处理敌机与主角的碰撞
for (int i = 0; i & vcEnemy.size(); i++) {
if (player.isCollsionWith(vcEnemy.elementAt(i))) {
// 发生碰撞,主角血量-1
player.setPlayerHp(player.getPlayerHp() - 1);
// 当主角血量小于0,判定游戏失败
if (player.getPlayerHp() &= -1) {
gameState = GAME_LOST;
//处理主角子弹逻辑
for (int i = 0; i & vcBulletPlayer.size(); i++) {
Bullet b = vcBulletPlayer.elementAt(i);
if (b.isDead) {
vcBulletPlayer.removeElement(b);
b.logic();
case GAME_WIN:
case GAME_LOST:
case GAME_PAUSE:
public void run() {
while (flag) {
long start = System.currentTimeMillis();
long end = System.currentTimeMillis();
if (end - start & 50) {
Thread.sleep(50 - (end - start));
} catch (InterruptedException e) {
e.printStackTrace();
* SurfaceView视图状态发生改变,响应此函数
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
* SurfaceView视图消亡时,响应此函数
public void surfaceDestroyed(SurfaceHolder holder) {
现在子弹碰撞主角 并没有发生事情 需要子弹和主角的碰撞检测
//修改Player类 添加碰撞检测
// // 判断碰撞(主角与敌机子弹)
public boolean isCollsionWith(Bullet bullet) {
// 是否处于无敌时间
if (isCollision == false) {
int x2 = bullet.bulletX;
int y2 = bullet.bulletY;
int w2 = bullet.bmpBullet.getWidth();
int h2 = bullet.bmpBullet.getHeight();
if (x &= x2 && x &= x2 + w2) {
} else if (x &= x2 && x + bmpPlayer.getWidth() &= x2) {
} else if (y &= y2 && y &= y2 + h2) {
} else if (y &= y2 && y + bmpPlayer.getHeight() &= y2) {
// 碰撞即进入无敌状态
isCollision =
// 处于无敌状态,无视碰撞
&在主界面 MySrufaceView 的逻辑函数中添加 主角和敌机子弹的碰撞
//处理敌机子弹与主角碰撞
for (int i = 0; i & vcBullet.size(); i++) {
if (player.isCollsionWith(vcBullet.elementAt(i))) {
//发生碰撞,主角血量-1
player.setPlayerHp(player.getPlayerHp() - 1);
//当主角血量小于0,判定游戏失败
if (player.getPlayerHp() &= -1) {
gameState = GAME_LOST;
当然 主角的子弹碰撞了敌机 也需要进行碰撞检测 修改 敌机类 Enemy
//判断碰撞(敌机与主角子弹碰撞)
public boolean isCollsionWith(Bullet bullet) {
int x2 = bullet.bulletX;
int y2 = bullet.bulletY;
int w2 = bullet.bmpBullet.getWidth();
int h2 = bullet.bmpBullet.getHeight();
if (x &= x2 && x &= x2 + w2) {
} else if (x &= x2 && x + frameW &= x2) {
} else if (y &= y2 && y &= y2 + h2) {
} else if (y &= y2 && y + frameH &= y2) {
//发生碰撞,让其死亡
在主视图中添加逻辑 主角子弹和敌机碰撞的逻辑
//处理主角子弹与敌机碰撞
for (int i = 0; i & vcBulletPlayer.size(); i++) {
//取出主角子弹容器的每个元素
Bullet blPlayer = vcBulletPlayer.elementAt(i);
for (int j = 0; j & vcEnemy.size(); j++) {
//添加爆炸效果 待完成
上面完成 的效果图
下面完成爆炸的效果
新建一个爆炸类 Boom
* 瞬间爆炸 类
* @author liuml
上午11:32:56
public class Boom {
//爆炸效果资源图
private Bitmap bmpB
//爆炸效果的位置坐标
private int boomX, boomY;
//爆炸动画播放当前的帧下标
private int cureentFrameI
//爆炸效果的总帧数
private int totleF
//每帧的宽高
private int frameW, frameH;
//是否播放完毕,优化处理
public boolean playE
//爆炸效果的构造函数
public Boom(Bitmap bmpBoom, int x, int y, int totleFrame) {
this.bmpBoom = bmpB
this.boomX =
this.boomY =
this.totleFrame = totleF
frameW = bmpBoom.getWidth() / totleF
frameH = bmpBoom.getHeight();
//爆炸效果绘制
public void draw(Canvas canvas, Paint paint) {
canvas.save();
canvas.clipRect(boomX, boomY, boomX + frameW, boomY + frameH);
canvas.drawBitmap(bmpBoom, boomX - cureentFrameIndex * frameW, boomY, paint);
canvas.restore();
//爆炸效果的逻辑
public void logic() {
if (cureentFrameIndex & totleFrame) {
cureentFrameIndex++;
下面就还是老套路了 在主界面 声明爆炸容器 然后绘制 然后是逻辑实现
package com.
import java.util.R
import java.util.V
import android.content.C
import android.content.res.R
import android.graphics.B
import android.graphics.BitmapF
import android.graphics.C
import android.graphics.C
import android.graphics.P
import android.view.KeyE
import android.view.MotionE
import android.view.SurfaceH
import android.view.SurfaceHolder.C
import android.view.SurfaceV
public class MySurfaceView extends SurfaceView implements Callback, Runnable {
private SurfaceH
// 1 定义游戏状态常量
public static final int GAME_MENU = 0;// 游戏菜单
public static final int GAMEING = 1;// 游戏中
public static final int GAME_WIN = 2;// 游戏胜利
public static final int GAME_LOST = 3;// 游戏失败
public static final int GAME_PAUSE = -1;// 游戏菜单
// 当前游戏状态(默认初始在游戏菜单界面)
public static int gameState = GAME_MENU;
// 声明一个Resources实例便于加载图片
private Resources res = this.getResources();
// 声明游戏需要用到的图片资源(图片声明)
private Bitmap bmpBackG// 游戏背景
private Bitmap bmpB// 爆炸效果
private Bitmap bmpBoosB// Boos爆炸效果
private Bitmap bmpB// 游戏开始按钮
private Bitmap bmpButtonP// 游戏开始按钮被点击
private Bitmap bmpEnemyD// 怪物鸭子
private Bitmap bmpEnemyF// 怪物苍蝇
private Bitmap bmpEnemyB// 怪物猪头Boos
private Bitmap bmpGameW// 游戏胜利背景
private Bitmap bmpGameL// 游戏失败背景
private Bitmap bmpP// 游戏主角飞机
private Bitmap bmpPlayerHp;// 主角飞机血量
private Bitmap bmpM// 菜单背景
public static Bitmap bmpB// 子弹
public static Bitmap bmpEnemyB// 敌机子弹
public static Bitmap bmpBossB// Boss子弹
public static int screenW;
public static int screenH;
// 声明一个敌机容器
private Vector&Enemy& vcE
// 每次生成敌机的时间(毫秒)
private int createEnemyTime = 50;
// 敌人数组:1和2表示敌机的种类,-1表示Boss
// 二维数组的每一维都是一组怪物
private int enemyArray[][] = { { 1, 2 }, { 1, 1 }, { 1, 3, 1, 2 },
{ 1, 2 }, { 2, 3 }, { 3, 1, 3 }, { 2, 2 }, { 1, 2 }, { 2, 2 },
{ 1, 3, 1, 1 }, { 2, 1 }, { 1, 3 }, { 2, 1 }, { -1 } };
// 当前取出一维数组的下标
private int enemyArrayI
// 是否出现Boss标识位
private boolean isB
// 随机库,为创建的敌机赋予随即坐标
private GameMenu gameM
private GameBg gameBg;
// 敌机子弹容器
private Vector&Bullet& vcB
// 添加子弹的计数器
private int countEnemyB
// 主角子弹容器
private Vector&Bullet& vcBulletP
// 添加子弹的计数器
private int countPlayerB
//爆炸效果容器
private Vector&Boom& vcB
* SurfaceView初始化函数
public MySurfaceView(Context context) {
super(context);
sfh = this.getHolder();
sfh.addCallback(this);
paint = new Paint();
paint.setColor(Color.WHITE);
paint.setAntiAlias(true);
setFocusable(true);
* SurfaceView视图创建,响应此函数
public void surfaceCreated(SurfaceHolder holder) {
screenW = this.getWidth();
screenH = this.getHeight();
initGame();
// 实例线程
th = new Thread(this);
// 启动线程
th.start();
* 加载游戏资源
private void initGame() {
// 加载游戏资源
bmpBackGround = BitmapFactory
.decodeResource(res, R.drawable.background);
bmpBoom = BitmapFactory.decodeResource(res, R.drawable.boom);
bmpBoosBoom = BitmapFactory.decodeResource(res, R.drawable.boos_boom);
bmpButton = BitmapFactory.decodeResource(res, R.drawable.button);
bmpButtonPress = BitmapFactory.decodeResource(res,
R.drawable.button_press);
bmpEnemyDuck = BitmapFactory.decodeResource(res, R.drawable.enemy_duck);
bmpEnemyFly = BitmapFactory.decodeResource(res, R.drawable.enemy_fly);
bmpEnemyBoos = BitmapFactory.decodeResource(res, R.drawable.enemy_pig);
bmpGameWin = BitmapFactory.decodeResource(res, R.drawable.gamewin);
bmpGameLost = BitmapFactory.decodeResource(res, R.drawable.gamelost);
bmpPlayer = BitmapFactory.decodeResource(res, R.drawable.player);
bmpPlayerHp = BitmapFactory.decodeResource(res, R.drawable.hp);
bmpMenu = BitmapFactory.decodeResource(res, R.drawable.menu);
bmpBullet = BitmapFactory.decodeResource(res, R.drawable.bullet);
bmpEnemyBullet = BitmapFactory.decodeResource(res,
R.drawable.bullet_enemy);
bmpBossBullet = BitmapFactory
.decodeResource(res, R.drawable.boosbullet);
// 菜单类实例化
gameMenu = new GameMenu(bmpMenu, bmpButton, bmpButtonPress);
// 实例游戏背景
gameBg = new GameBg(bmpBackGround);
// 实例主角
player = new Player(bmpPlayer, bmpPlayerHp);
//敌机子弹容器实例
vcBullet = new Vector&Bullet&();
//主角子弹容器实例
vcBulletPlayer = new Vector&Bullet&();
// 实例敌机容器
vcEnemy = new Vector&Enemy&();
// 实例随机库
random = new Random();
//爆炸效果容器实例
vcBoom = new Vector&Boom&();
* 游戏绘图
public void myDraw() {
canvas = sfh.lockCanvas();
if (canvas != null) {
canvas.drawColor(Color.WHITE);
// 绘图函数根据游戏状态不同进行不同绘制
switch (gameState) {
case GAME_MENU:
gameMenu.draw(canvas, paint);
case GAMEING:
gameBg.draw(canvas, paint);
player.draw(canvas, paint);
if (isBoss == false) {
// 敌机绘制
for (int i = 0; i & vcEnemy.size(); i++) {
vcEnemy.elementAt(i).draw(canvas, paint);
//敌机子弹绘制
for (int i = 0; i & vcBullet.size(); i++) {
vcBullet.elementAt(i).draw(canvas, paint);
//爆炸效果绘制
for (int i = 0; i & vcBoom.size(); i++) {
vcBoom.elementAt(i).draw(canvas, paint);
// boss 绘制
// 处理主角子弹绘制
for (int i = 0; i & vcBulletPlayer.size(); i++) {
vcBulletPlayer.elementAt(i).draw(canvas, paint);
case GAME_WIN:
case GAME_LOST:
case GAME_PAUSE:
} catch (Exception e) {
// TODO: handle exception
} finally {
if (canvas != null)
sfh.unlockCanvasAndPost(canvas);
* 触屏事件监听
public boolean onTouchEvent(MotionEvent event) {
switch (gameState) {
case GAME_MENU:
gameMenu.onTouchEvent(event);
case GAMEING:
case GAME_WIN:
case GAME_LOST:
case GAME_PAUSE:
* 按键事件监听
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (gameState) {
case GAME_MENU:
case GAMEING:
player.onKeyDown(keyCode, event);
case GAME_WIN:
case GAME_LOST:
case GAME_PAUSE:
return super.onKeyDown(keyCode, event);
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (gameState) {
case GAME_MENU:
case GAMEING:
player.onKeyUp(keyCode, event);
case GAME_WIN:
case GAME_LOST:
case GAME_PAUSE:
return super.onKeyUp(keyCode, event);
* 游戏逻辑
private void logic() {
switch (gameState) {
case GAME_MENU:
case GAMEING:
gameBg.logic();
player.logic();
// 敌机逻辑
if (isBoss == false) {
// 敌机逻辑
for (int i = 0; i & vcEnemy.size(); i++) {
Enemy en = vcEnemy.elementAt(i);
// 因为容器不断添加敌机 ,那么对敌机isDead判定,
// 如果已死亡那么就从容器中删除,对容器起到了优化作用;
if (en.isDead) {
vcEnemy.removeElementAt(i);
en.logic();
// 生成敌机
if (count % createEnemyTime == 0) {
for (int i = 0; i & enemyArray[enemyArrayIndex]. i++) {
if (enemyArray[enemyArrayIndex][i] == 1) {
int x = random.nextInt(screenW - 100) + 50;
vcEnemy.addElement(new Enemy(bmpEnemyFly, 1, x, -50));
} else if (enemyArray[enemyArrayIndex][i] == 2) {
int y = random.nextInt(20);
vcEnemy.addElement(new Enemy(bmpEnemyDuck, 2, -50,
} else if (enemyArray[enemyArrayIndex][i] == 3) {
int y = random.nextInt(20);
vcEnemy.addElement(new Enemy(bmpEnemyDuck, 3,
screenW + 50, y));
// 这里判断下一组是否为最后一组(Boss)
if (enemyArrayIndex == enemyArray.length - 1) {
enemyArrayIndex++;
// 每2秒添加一个敌机子弹
countEnemyBullet++;
if (countEnemyBullet % 40 == 0) {
for (int i = 0; i & vcEnemy.size(); i++) {
Enemy en = vcEnemy.elementAt(i);
// 不同类型敌机不同的子弹运行轨迹
int bulletType = 0;
switch (en.type) {
case Enemy.TYPE_FLY:
bulletType = Bullet.BULLET_FLY;
case Enemy.TYPE_DUCKL:
case Enemy.TYPE_DUCKR:
bulletType = Bullet.BULLET_DUCK;
vcBullet.add(new Bullet(bmpEnemyBullet, en.x + 10,
en.y + 20, bulletType));
// 处理敌机子弹逻辑
for (int i = 0; i & vcBullet.size(); i++) {
Bullet b = vcBullet.elementAt(i);
if (b.isDead) {
vcBullet.removeElement(b);
b.logic();
//每1秒添加一个主角子弹
countPlayerBullet++;
if (countPlayerBullet % 20 == 0) {
vcBulletPlayer.add(new Bullet(bmpBullet, player.x + 15, player.y - 20, Bullet.BULLET_PLAYER));
// 处理敌机与主角的碰撞
for (int i = 0; i & vcEnemy.size(); i++) {
if (player.isCollsionWith(vcEnemy.elementAt(i))) {
// 发生碰撞,主角血量-1
player.setPlayerHp(player.getPlayerHp() - 1);
// 当主角血量小于0,判定游戏失败
if (player.getPlayerHp() &= -1) {
gameState = GAME_LOST;
//处理主角子弹逻辑
for (int i = 0; i & vcBulletPlayer.size(); i++) {
Bullet b = vcBulletPlayer.elementAt(i);
if (b.isDead) {
vcBulletPlayer.removeElement(b);
b.logic();
//处理敌机子弹与主角碰撞
for (int i = 0; i & vcBullet.size(); i++) {
if (player.isCollsionWith(vcBullet.elementAt(i))) {
//发生碰撞,主角血量-1
player.setPlayerHp(player.getPlayerHp() - 1);
//当主角血量小于0,判定游戏失败
if (player.getPlayerHp() &= -1) {
gameState = GAME_LOST;
//处理主角子弹与敌机碰撞
for (int i = 0; i & vcBulletPlayer.size(); i++) {
//取出主角子弹容器的每个元素
Bullet blPlayer = vcBulletPlayer.elementAt(i);
for (int j = 0; j & vcEnemy.size(); j++) {
//添加爆炸效果
//取出敌机容器的每个元与主角子弹遍历判断
if (vcEnemy.elementAt(j).isCollsionWith(blPlayer)) {
vcBoom.add(new Boom(bmpBoom, vcEnemy.elementAt(j).x, vcEnemy.elementAt(j).y, 7));
case GAME_WIN:
case GAME_LOST:
case GAME_PAUSE:
public void run() {
while (flag) {
long start = System.currentTimeMillis();
long end = System.currentTimeMillis();
if (end - start & 50) {
Thread.sleep(50 - (end - start));
} catch (InterruptedException e) {
e.printStackTrace();
* SurfaceView视图状态发生改变,响应此函数
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
* SurfaceView视图消亡时,响应此函数
public void surfaceDestroyed(SurfaceHolder holder) {
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具

我要回帖

更多关于 一个子弹消灭一个敌人 的文章

 

随机推荐