Processing编程——仿雷电STG

  • 1.前言
  • 2.内容展示
  • 3.实现过程
    • 3.1.背景云彩的随机生成
    • 3.2.飞行尾气的实现
    • 3.3.击中敌人的粒子效果
    • 3.4怪物类
    • 3.5.武器系统
  • 4.一些问题
  • 5.总结

非常幸运这个学期在互动媒体技术这门课上深入的了解了Daniel Shiffman的《代码本色 The Nature of Code》 这本书,在课程最后,老师也是希望我们能利用书中的内容做一个交互应用出来,这就是我们本次博文内容的主题啦。

1.前言

那么怎么才能让这个交互小应用变得足够有趣呢,我思考了很多的表现形式,最终还是回到了我比较熟悉的游戏上来。
当然,可供选择的游戏模式依旧有很多,正好在思考这个问题的几天里,我的网易云推给了我一首FC游戏的bgm,一下子无数回忆涌上心头,就想使用processing仿照着去写一个小时候玩过的《雷电》。

2.内容展示

3.实现过程

首先我们需要实现这个小应用需要什么功能,然后再把这些功能抽象成一个个类,这样实现起来会方便很多。
然后我们可以想到,我们需要的有:子弹类,主角类,云彩类,怪物类,飞机尾气类还有子弹消失的粒子效果类。
这些类别共同构成了我们可以进行交互娱乐的游戏应用,接下来我们就几个关键技术看他们的具体实现。

3.1.背景云彩的随机生成

在这份小游戏中,背景由天蓝色的整体颜色以及白色的云朵组成,在这里我们可以设定云彩的数量上限,然后在每次初始化的时候进行随机生成。

class cloud {int num_cloud;float[] bgptx;float[] bgpty;cloud(int num) {bgptx = new float[num];bgpty = new float[num];num_cloud = num;for (int i = 0; i<num_cloud; i++) {bgptx[i] = random(-width*0.4, boxx+width*0.4);bgpty[i] = random(-height*0.4, boxy+height*0.4);}}void update() {show();}void show() {for (int i = 0; i<num_cloud; i++) {noStroke();fill(255);ellipse(bgptx[i]+anchordist.x, bgpty[i]+anchordist.y, 130, 130);ellipse(bgptx[i]+anchordist.x+80, bgpty[i]+anchordist.y+10, 100, 100);ellipse(bgptx[i]+anchordist.x+130, bgpty[i]+anchordist.y+30, 55, 55);ellipse(bgptx[i]+anchordist.x-80, bgpty[i]+anchordist.y+10, 95, 95);}}
}

在这里我们可以看到,cloud在执行构造函数时,每次都会通过random()函数随机地获得一个坐标位置,然后在show()函数中,在这个随机位置上,绘制云彩的图案。

然后我们在背景类中实体化云彩类,最后在主页sketch中调用实体化的背景类——层层调用。

// 背景类的构造函数
background() {bds = new bullet_die_particle ();cl = new cloud(20);// 每次生成20朵云}
// sketch主页上的调用
public background bg;
bg = new background();
void draw() {bg.show();}

3.2.飞行尾气的实现


要实现每次按动方向键就能出现飞行尾气,我们首先需要能产生“一条”尾气。
所以我们这里建立两个类,一个onefire,一个powerFire,虽然二者至今没有直接的继承关系,但是由于他们关系密切,我们将他们放在一个标签页中。
这里我们可以想到,对于“一条”尾气来说,他应该有三个参数,位置,速度,以及判断是否处在“加速”状态(方向键按下)。
接下来我们看一下onefire类的构造函数。

onefire(PVector loc0, PVector vel0, boolean powerup) {loc = new PVector(loc0.x, loc0.y);float anc;if (powerup) {anc = random(-an08, an08);velborn*=1.5;} else {anc = random(-an16, an16);}vel = new PVector(vel0.x, vel0.y);vel.normalize();vel = rotateangle(new PVector(vel.x, vel.y), anc);vel.mult(velborn);if (powerup) {float absanc = abs(anc);if (absanc>an32) {dieline = normallife+int(random(-10, 10));c = c2;if (absanc>an16) {dieline = shortlife+int(random(-10, 10));r*=0.6;c = c3;}} else {dieline = lonelife+int(random(-10, 10));c = c1;r*=1.4;}} else {float absanc = abs(anc);if (absanc>an64) {dieline = normallife+int(random(-10, 10));c = c2;if (absanc>an32) {dieline = shortlife+int(random(-10, 10));c = c3;}} else {dieline = lonelife+int(random(-10, 10));c = c1;}}}

这里可以看到,每一条尾气都是由三部分组成,也就是说,三种长短不一的尾气组成了一条尾气。这么介绍下来可能有些绕口,但是应该比较容易理解。
在onefire类中还涉及几种简单的类方法,比如show()绘制尾气,update()在draw()中调用用来更新尾气。
然后我们来看powerFire类
这个类就是将onefire类实体化,同时增加一个add方法,提供给主角类,主角类在加速时,可以调用add方法,在画面上增加尾气。

class powerfire {ArrayList<onefire> fire;powerfire() {fire = new ArrayList<onefire>();}void update() {rectMode(CENTER);noStroke();for (int i =0; i<fire.size(); i++) {onefire ft = fire.get(i);if (ft.timer()) {fire.remove(i);} else {ft.update();ft.show();}}}void addfire(PVector loc, PVector vel, boolean powerup) {vel.normalize();  for (int i = 20; i>0; i--) {fire.add(new onefire(new PVector(loc.x, loc.y), new PVector(vel.x, vel.y), powerup));}}
}

3.3.击中敌人的粒子效果


关于这个系统的笼统介绍就是,挡子弹碰到敌人或者墙壁后,可以以散射状绽开。
这里有三个相关类,particleWithoutAcc,bullet_die,bullet_die_particle这三个类。
particleWithoutAcc中主要是一些获得当前子弹的颜色,速度,以及子弹大小的基础方法。
然后在bullet_die中
它继承自particleWithoutAcc类,依靠父类的方法进行初始化,除此之外有一个show()方法,根据子弹大小绘制出子弹碎片。

class bullet_die extends particleWithoutAcc { bullet_die(PVector loc, PVector vel, color c) {this.loc = new PVector(loc.x, loc.y);this.vel = new PVector(vel.x, vel.y);setcolor(c);setlife(int(framerate*1));setrad(4);}void show() {if (!outboder(loc, rad/2)) {pushMatrix();translate(loc.x+anchordist.x, loc.y+anchordist.y);rotate(atan2(-vel.y, -vel.x));strokeWeight(rad*map(age, 0, life, 1, 0.5));stroke(c);line(-8*map(age, 0, life, 1, 0), 0, 0, 0);popMatrix();}}
}

bullet_die_particle中主要是将bullet_die实例化后,根据当前位置和速度用大量的if语句来进行子弹碎片绽开的角度判断。
这些都放在add方法中

void addbdp(PVector loc, PVector vel, color c, boolean isDieboder, boolean R, boolean L, boolean U, boolean D) {totaladd++;float angleB;float angleE;if (isDieboder) {angleB = 0;angleE = TWO_PI;if (U) {angleB = 0;angleE = PI;} else {if (D) {angleB = PI;angleE = TWO_PI;}}if (R) {angleB = HALF_PI;angleE = HALF_PI*3;if (U) {angleE = PI;}if (D) {angleB = PI;}} else {if (L) {angleB = -HALF_PI;angleE = HALF_PI;if (U) {angleB = 0;} else {if (D) {angleE = 0;}}}}} else {float angle = atan2(vel.y, vel.x);if (angle>=umbrellaAngle||angle<=-umbrellaAngle) {angle+=TWO_PI;}angleB = angle-umbrellaAngle/2;angleE = angle+umbrellaAngle/2;}for (float i = angleB; i<=angleE; i+=borndist) {bdp.add(new bullet_die(new PVector(loc.x, loc.y), new PVector(cos(i)*velnum, sin(i)*velnum), c));}}

3.4怪物类

在monster的实现上,我实现了一个monster系统来管理几种monster。
所以这里有这么几种方法,monster类及它的三个子类——具体的怪物,还有一个monstersystem类。
在monster中,主要是初始化一些参数,比如位置,速度,加速度等参数。
在monster子类中,主要是利用他们的show()方法,绘制图形,还有check()方法进行碰撞检测。这里展示一下碰撞检测。

 void check() {if (PVector.dist(toc, moe.loc)<moe.r/2+rad/2) {moe.blood-=5;}int i = 0;while (!isDie&&i<moe.bs.bn.size()) {if (PVector.dist(toc, moe.bs.bn.get(i).loc)<=moe.bs.bn.get(i).rad/2+rad/2) {moe.bs.bn.get(i).isDie = true;isDie = true;}i++;}}

其中的moe是主角类的实例。
最后是monstersystem类,其中比较重要的就是add方法,它会在角色周围自动生成怪物。
用怪物1来举例

void addm1(int i) {//could code be betterif (M1.size()<5) {for (int c = 0; c<i; c++) {float angle = random(-PI, PI);float disting = random(300, 1000);float btx = disting*cos(angle)+moe.loc.x;float bty = disting*sin(angle)+moe.loc.y;btx = range(btx, ms0DistMoe, boxx-ms0DistMoe);bty = range(bty, ms0DistMoe, boxy-ms0DistMoe);M1.add(new monster_splite(new PVector(btx, bty)));}}}

3.5.武器系统

武器系统主要由键盘事件,主角类和子弹类共同实现。
bullet_normal类中有子弹的初始化方法。

void init_normal(color c, int vel, int rad) {velborn = vel;ms = 0.5;damp = 0.99;maxvel = 20;tagaccN = 1;setcolor(c);setrad(rad);}

在速度之外,我还在初始化中添加了颜色和子弹大小。
然后在bullet类中,使用了一个switch-case语句,来进行武器的选择。

 void addbs(PVector loc, PVector vel, int mod, boolean powerup) {switch(mod) {case 1:addbn1(loc, vel, powerup);return;case 2:addbn2(loc, vel, powerup);return;case 3:addbn3(loc, vel, powerup);return;case 4:addUltimateB(loc, vel, powerup);return;}}

可以看到,mod变量不同,提供的子弹类别也不同。
关于变量mod的改变,主要是在键盘事件中。

if (key !=CODED) {if (keyCode == '1') {moe.setcolor(color(161, 23, 21));mod = 1;}if (keyCode == '2') {moe.setcolor(color(0, 90, 171));mod = 2;}if (keyCode == '3') {moe.setcolor(color(6, 128, 67));mod = 3;}

我们可以使用数字键切换武器,同时调用主角类的方法,改变主角机体的颜色。就像《雷电》里一样。机体颜色对应着武器。



当然,我也给他添加了一个终极技能,每次游戏开始有三次释放机会,图示在我们最开始的一张图中。

4.一些问题

虽然磕磕碰碰,过程中看了很多的示例,最后的还原度也就到这个程度了。
没有能够实现的点有这么几个:
道具系统——武器应该是根据道具来改变,并且提升强度
卷轴效果——画面能与角色同步移动并且没有严格意义上的边界
素材加载——不是使用函数绘制而是通过素材加载展现内容
难度选择——可以手动选择难度

这些问题有一些是因为平台限制实现起来不方便,有一些是还没有想好怎样解决,希望以后可以实现优化,自己做一个好玩的stg弹幕射击游戏。

5.总结

经过这段时间的学习,对processing编程有了更深的理解,学会了更加灵活地使用向量,在程序中使用物理法则等等。
总之,这次的作业到这儿就暂告一段落了,搭建框架和后期微调都花了不少的时间,整个游戏几遍玩下来,也算有趣,但就是游戏内容不多,容易腻味,希望之后有时间能优化或者用别的工具重新写一下。

使用processing写一个仿雷电小游戏相关推荐

  1. 【牛客刷题】上手用C语言写一个三子棋小游戏超详解哦(电脑优化)

    作者:[南航科院小张 南航科院小张的博客 专栏:从c语言的入门到进阶 学习知识不只是要懂,还要会用:想要找到好的工作,这里给大家介绍一件可以斩获诸多大厂offer的利器–牛客网 点击免费注册和我一起开 ...

  2. 你写一个web网页小游戏

    写一个 web 网页小游戏需要以下几个步骤: 选择一种编程语言,常用的有 HTML.CSS.JavaScript 和 Python. 使用编辑器创建一个 HTML 文件,这个文件将是你的网页的基础. ...

  3. c语言写一个简单的小游戏-推箱子

    在学习C语言之后,写了一个简单的小游戏来锻炼自己的代码以及C语言知识的掌握能力. 推箱子作为手机上最常见的简单游戏,其代码也相对简单,想法也比较简单,下面为其代码和运行图. /************ ...

  4. 一个简单的c 游戏编程语言,编程达人 c语言写一个简单的小游戏-推箱子

    在学习C语言之后,写了一个简单的小游戏来锻炼自己的代码以及C语言知识的掌握能力. 推箱子作为手机上最常见的简单游戏,其代码也相对简单,想法也比较简单,下面为其代码和运行图. /************ ...

  5. 用c++帮我写一个闯关小游戏

    很高兴为您写一个闯关小游戏!这个游戏将分为3个关卡,每个关卡都有不同的挑战.第一关的挑战是收集3个物品,这些物品分别在不同的位置,你必须找到它们才能过关.第二关的挑战是找到一个宝藏,你必须通过解决难题 ...

  6. vs2010c语言小游戏,用C语言写一个三子棋小游戏(用VS2010实现,加强版)

    前几天写了一个三子棋小游戏,但是比较简单,因为以前写的游戏棋盘只能是3x3那么大.今天对那个程序做了两点改进: 1.现在可以实现在任意大小的棋盘上下棋了. 2.因为棋盘可能变大,为了玩家方便确定坐标, ...

  7. c++编写手机小游戏代码_玩过自己开发的贪吃蛇吗?点这里,教你用Python写一个贪吃蛇小游戏!(附源代码)...

    后台回复'0816',加入Python交流群~ 往日回顾:Python必读好书,这9本份量十足~ 本文代码的实现效果,获取源代码,请直接滑到文末~都说Python除了生孩子,什么都能干.咱们今天,就用 ...

  8. 用C语言写一个简单的小游戏——猜数字

    我们该如何设计这个程序? 1.首先应该打印一个菜单,让玩家选择玩游戏或者退出游戏 2.当玩家选择玩游戏,我们让电脑生成一个1~100的随机数,让玩家去猜 3.如果玩家猜的数比电脑生成的数大,我们提示猜 ...

  9. Java写一个黄金矿工小游戏

    写这个小游戏的初衷 同学一起互助学习 前两天和一个计科的高中同学交流想法,有讲到合理规划时间,然后用分出来的时间去网上找资源学一些项目,这不,就有了这个小游戏了 和同学交流的时候,对方说每周花一个小时 ...

最新文章

  1. python3 获取cpu 内存利用率
  2. Python3学习笔记——类
  3. 做shopee找代运营,如何判断一家代运营公司是否靠谱?
  4. python开始print_当你使用print时,Python是怎么运行的
  5. 计算机基础:多媒体基础知识笔记
  6. 出现特殊分隔符无法分隔解决方案
  7. 演练 打印直角三角形
  8. python 执行shell_python执行shell命令四法
  9. blender_(uv应用)................http://digitalman.blog.163.com/blog/static/23874605620174172058299/...
  10. GraphLite 实现子图匹配
  11. python爬虫模拟点击和输入_爬虫笔记关于鼠标点击和内容输入
  12. 西电计算机学院通知,西安电子科技大学计算机科学与技术学院关于发放2020级硕士研究生正式录取通知书的通知...
  13. 最新 lineageos 编译过程 详细过程
  14. debian系统使用NTP服务器并自动同步时间
  15. 系统监控必备工具procmon
  16. Ubuntu Linux出现IP inet6 addr: fe80::fe0:9b43:8a0e:2463/64的解决办法
  17. 十六.Elasticsearch Adjacency Matrix Aggregation
  18. Linux tar过滤文件
  19. greasemonkey_在Firefox中更改或设置Greasemonkey脚本编辑器
  20. 如何做一个基于python校园失物招领系统毕业设计毕设作品(Django框架)

热门文章

  1. 谷安天下2013年6月CISA考前辅导 第一季
  2. LeetCode - 1162 地图分析
  3. 惠普HP LaserJet Pro 400-M401d 打印机打印出的纸出现雨水滴在玻璃的现象!!
  4. ABAP ALV 总结
  5. apache ii评分怎么评_APACHEII评分表-新(最新整理)
  6. Android的无边界程序设计理念
  7. chrome系浏览器插件:chromoji - 替换默认emoji,解决不显示emoji的问题
  8. 以太坊Solidity----什么是ABI?
  9. ACM: SCU 4438 Censor - KMP
  10. macOS逆向(MindNode)