可能会持续更新吧,,

我们说一下固定弹,直线轨迹的做法 .

首先放一个 Kaguya 的波粒:

境符「波与粒的境界」

since C++98,系统要求 Windows .

#include <cmath>
#include <cstdio>
#include <conio.h>
#include <cstdlib>
#include <windows.h>
using namespace std;
const int hs = 28, vs = 65;
const double pi = 3.1415926, sx = 14, sy = 17;
char ed[hs];
char sqr[hs][vs];
void *bin = NULL;
struct nol_bul
{
nol_bul *last, *next;
double x, y, dx, dy; bool move()
{
this->x += this->dx;
this->y += this->dy;
int ix = (int)this->x, iy = (int)(this->y * 2 + 0.5);
if (ix >= hs || ix < 0 || iy >= vs || iy < 0)
{
(*(this->last)).next = (this->next);
if (this->next != NULL)
(*(this->next)).last = this->last;
return true;
}
if (iy > ed[ix])
ed[ix] = iy;
sqr[ix][iy] = '.';
return false;
}
}; struct player
{
int x, y; void move()
{
int in = 0;
while (_kbhit())
{
in = _getch();
if (in == 72)
this->x--;
else if (in == 80)
this->x++;
else if (in == 75)
this->y--;
else if (in == 77)
this->y++;
}
int tmp = this->y << 1;
if (this->x >= hs)
this->x = hs - 1;
if (this->x < 0)
this->x = 0;
if (tmp >= vs)
this->y = (vs >> 1) - 1;
if (tmp < 0)
this->y = 0;
if (sqr[this->x][tmp] == '.')
{
Sleep(1200);
exit(0);
}
if (tmp > ed[this->x])
ed[this->x] = tmp;
sqr[this->x][tmp] = '0';
return;
}
}; void put(nol_bul&, int); int main()
{
//初始化
for (int i = 0; i < hs; i++)
{
for (int j = 0; j < vs; j++)
sqr[i][j] = ' ';
ed[i] = -1;
}
int k = 5, a = 5, wait = 0;
nol_bul emp;
nol_bul *p = NULL, *net = NULL;
emp.x = sx;
emp.y = sy;
emp.dx = emp.dy = 0;
emp.last = emp.next = NULL;
player sel;
sel.x = hs - 2;
sel.y = (int)sy;
printf ("press to start");
_getch(); while (1)
{
system("cls");
for (int i = 0; i < hs; i++)
{
for (int j = 0; j <= ed[i]; j++)
{
putchar(sqr[i][j]);
sqr[i][j] = ' ';
}
putchar('\n');
ed[i] = -1;
} if (wait == 1)
{
k += 4;
if (k >= 360)
k -= 360;
a += k;
if (a >= 360)
a -= 360;
for (int i = 0; i < 360; i += 72)
put(emp, a + i);
wait = 0;
}else
wait = 1;
p = &emp;
while (p)
{
net = (*p).next;
if ((*p).move())
delete p;
p = net;
}
sel.move(); Sleep(10);
}
return 0;
} void put(nol_bul &emp, int a)
{
nol_bul *tmp = new nol_bul;
(*tmp).last = &emp;
(*tmp).next = emp.next;
if (emp.next)
(*(emp.next)).last = tmp;
emp.next = tmp;
(*tmp).x = sx;
(*tmp).y = sy;
(*tmp).dx = 0.7 * cos(a * pi / 180);
(*tmp).dy = 0.7 * sin(a * pi / 180);
}

我们仔细分析这个代码,可以发现 hs, vs 是屏幕大小,sx, sy 是敌机坐标 .

nol_bul 是子弹类(直线移动),x, y 是目前坐标,dx, dy 是移动变动量(\(x\gets x + dx\),\(y\gets y + dx\)),那个 this->y * 2 + 0.5 是为了让屏幕看起来方一点 .

然后就是显示之类,本质相同,核心部分就在于 put 函数,它接收一个子弹 emp 和一个随时间变化的参数 a,然后将 emp 初始化 .

在波粒中,a 就是一个角度变量(后面我们把它叫做 \(\alpha\),弧度制),它不断的随时间转动,而坐标增量的计算(斜率)则是简单的正余弦,我们可以列出表达式:

\[\begin{cases}\Delta x = 0.7\cos\alpha\\ \Delta y = 0.7\sin\alpha\end{cases}
\]

于是直线的方程即可写作(\((s_x,s_y)\) 是初始坐标)

\[y-s_y=\dfrac{\Delta y}{\Delta x}\cdot(x - s_x)
\]

\[y=Fx+s_y-Fs_x
\]

其中 \(F=\dfrac{\cos\alpha}{\sin\alpha}=\dfrac{1}{\tan{\alpha}}\) .

我们发现这个 \(0.7\) 根本没有用!然而事实上,直线是连续的,屏幕是离散的,我们在控制台中只能设置整数点,于是就有了这个 \(0.7\),你也可以看作是弹幕速度 .

通过这些奥妙重重的东西,我们就生成了一个波与粒的境界!

一些比较有意思的魔改(put):

魔改 1 (2, y0, y1)
void put(nol_bul &emp, int a)
{
nol_bul *tmp = new nol_bul;
(*tmp).last = &emp;
(*tmp).next = emp.next;
if (emp.next)
(*(emp.next)).last = tmp;
emp.next = tmp;
(*tmp).x = sx;
(*tmp).y = sy;
(*tmp).dx = 2 * y0(a * pi / 180);
(*tmp).dy = 2 * y1(a * pi / 180);
}
魔改 2(0.7,tanh,tan)

虽然敌机上面是安定但是安定点其实很难到达(准备改成自机狙

void put(nol_bul &emp, int a)
{
nol_bul *tmp = new nol_bul;
(*tmp).last = &emp;
(*tmp).next = emp.next;
if (emp.next)
(*(emp.next)).last = tmp;
emp.next = tmp;
(*tmp).x = sx;
(*tmp).y = sy;
(*tmp).dx = 0.7 * tanh(a * pi / 180);
(*tmp).dy = 0.7 * tan(a * pi / 180);
}
魔改 3(0.7, cos, sin 加扰动)
void put(nol_bul &emp, int a)
{
nol_bul *tmp = new nol_bul;
(*tmp).last = &emp;
(*tmp).next = emp.next;
if (emp.next)
(*(emp.next)).last = tmp;
emp.next = tmp;
(*tmp).x = sx;
(*tmp).y = sy;
double p = 0.01 * cosh(1 / M_E * acos(fmod(a, 2) - 1)), q = 0.01 * sinh(1 / M_E * asin(fmod(a, 2) - 1));
int T = 100;
while (T--)
{
double old_p = p, old_q = q;
p = fmod(sin(old_p) * cos(old_q) + 114514, 2) - 1;
q = fmod(acos(old_q) * asin(old_q) + 1919810, 2) - 1;
} p = 1 - 0.1 * p; q = 1 + 0.2 * q;
(*tmp).dx = 0.8 * p * sin((a + log(1 / q)) * pi / 180);
(*tmp).dy = 0.8 * q * cos((a - log(1 / p)) * pi / 180);
}
增加重开机制
#include <cmath>
#include <cstdio>
#include <conio.h>
#include <cstdlib>
#include <windows.h>
using namespace std;
const int hs = 28, vs = 65;
const double pi = 3.1415926, sx = 14, sy = 17;
char ed[hs];
char sqr[hs][vs];
void *bin = NULL;
bool fuck = false;
struct nol_bul
{
nol_bul *last, *next;
double x, y, dx, dy; bool move()
{
this->x += this->dx;
this->y += this->dy;
int ix = (int)this->x, iy = (int)(this->y * 2 + 0.5);
if (ix >= hs || ix < 0 || iy >= vs || iy < 0)
{
(*(this->last)).next = (this->next);
if (this->next != NULL)
(*(this->next)).last = this->last;
return true;
}
if (iy > ed[ix])
ed[ix] = iy;
sqr[ix][iy] = '.';
return false;
}
}; int main(); struct player
{
int x, y; void move()
{
int in = 0;
while (_kbhit())
{
in = _getch();
if (in == 72)
this->x--;
else if (in == 80)
this->x++;
else if (in == 75)
this->y--;
else if (in == 77)
this->y++;
}
int tmp = this->y << 1;
if (this->x >= hs)
this->x = hs - 1;
if (this->x < 0)
this->x = 0;
if (tmp >= vs)
this->y = (vs >> 1) - 1;
if (tmp < 0)
this->y = 0;
if (sqr[this->x][tmp] == '.')
{
Sleep(1200);
system("cls");
puts("You lose!");
puts("Again? ");
fuck = true;
main();
exit(0);
}
if (tmp > ed[this->x])
ed[this->x] = tmp;
sqr[this->x][tmp] = '0';
return;
}
}; void put(nol_bul&, int); int main()
{
//初始化
for (int i = 0; i < hs; i++)
{
for (int j = 0; j < vs; j++)
sqr[i][j] = ' ';
ed[i] = -1;
}
int k = 5, a = 5, wait = 0;
nol_bul emp;
nol_bul *p = NULL, *net = NULL;
emp.x = sx;
emp.y = sy;
emp.dx = emp.dy = 0;
emp.last = emp.next = NULL;
player sel;
sel.x = hs - 2;
sel.y = (int)sy;
printf ("press to start");
if (fuck) Sleep(500);
_getch();
while (1)
{
system("cls");
for (int i = 0; i < hs; i++)
{
for (int j = 0; j <= ed[i]; j++)
{
putchar(sqr[i][j]);
sqr[i][j] = ' ';
}
putchar('\n');
ed[i] = -1;
} if (wait == 1)
{
k += 4;
if (k >= 360)
k -= 360;
a += k;
if (a >= 360)
a -= 360;
for (int i = 0; i < 360; i += 72)
put(emp, a + i);
wait = 0;
}else
wait = 1;
p = &emp;
while (p)
{
net = (*p).next;
if ((*p).move())
delete p;
p = net;
}
sel.move(); Sleep(10);
}
return 0;
} void put(nol_bul &emp, int a)
{
nol_bul *tmp = new nol_bul;
(*tmp).last = &emp;
(*tmp).next = emp.next;
if (emp.next)
(*(emp.next)).last = tmp;
emp.next = tmp;
(*tmp).x = sx;
(*tmp).y = sy;
(*tmp).dx = 0.7 * cos(a * pi / 180);
(*tmp).dy = 0.7 * sin(a * pi / 180);
}

C++ 弹幕游戏的更多相关文章

  1. 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程

    数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...

  2. GOOGLE CODE ANDROID 开源项目 集合

    转:http://blog.csdn.net/dellheng/article/details/7163333 1.        ZXing  http://code.google.com/p/zx ...

  3. android开源项目集合

    ZXing http://code.google.com/p/zxing/ 条形码.二维码 K-9 Mail http://code.google.com/p/k9mail/ 邮件客户端 Sipdro ...

  4. 《Eroico》关卡与操作设计

    操作设计: 没有给明操作教程,操作全靠蒙,只有改建的位置可以看到. 但游戏的难度并没有给玩家适应操作感,随着难度提升怪物血量增厚,但怪物并没有僵直英雄却有僵直.第一个小猫妖便给了玩家一个痛击. 方向键 ...

  5. [游记] pkusc 2021 游记

    流水账 Day-4 写了ICPC的一道DP,有点细节,虽然写得有点难受,但挺好玩 Day-3 写了PKUSC2018最水的一题 是随机开的题 Day-2 可以去pkusc了,从今天中午开始停课 刚吃完 ...

  6. 《Genesis-3D开源游戏引擎完整实例教程-2D射击游戏篇08:弹幕系统》本系列完结

    8.弹幕系统 弹幕系统概述: 弹幕系统的设计体现了射击游戏的基本要素,玩家要在敌人放出的大量子弹(弹幕)的细小空隙间闪避,能在玩家闪躲弹幕的时候给玩家带来快感,接近满屏的子弹,增加了对玩家的视觉冲击力 ...

  7. 游戏AI系列内容 咋样才能做个有意思的AI呢

    游戏AI系列内容 咋样才能做个有意思的AI呢 写在前面的话 怪物AI怎么才能做的比较有意思.其实这个命题有点大,我作为一个仅仅进入游戏行业两年接触怪物AI还不到一年的程序员来说,来谈这个话题,我想我是 ...

  8. 游戏启示录 关于Update的相关问题

    游戏启示录 关于Update的相关问题 这里说的Update是指的游戏的主循环.一般情况下.为了程序的方便控制我们一般只会有一个主循环.所有的游戏逻辑都会在这一个循环中完成.(额,其实这么做有点浪费. ...

  9. android 弹幕效果demo

    记得之前有位朋友在我的公众号里问过我,像直播的那种弹幕功能该如何实现?如今直播行业确实是非常火爆啊,大大小小的公司都要涉足一下直播的领域,用斗鱼的话来讲,现在就是千播之战.而弹幕则无疑是直播功能当中最 ...

随机推荐

  1. linux篇-公司网络故障那些事(路由器变交换机)

    首先这次网络故障是断电引起的 我给大家画个模型 三层的为八口交换机 一层的为五口打印机 笔记本代表两台无线打印机 首先八口的连接了公司采购电脑一台,业务电脑一台,其他电脑三台 第二个五口交换的连接财务 ...

  2. unity---2d游戏杂记

    2d游戏制作的笔记 save Layout 增加配置 Packges文件夹 插件 调整视野 鼠标中键 拉近拉远 鼠标右键 平移 Alt+鼠标左键 移动视角 Pivot/Center 当前物体中心和多个 ...

  3. 146_ACCESS之HR招聘信息管理_64位

    焦棚子的文章目录 点击下载附件 一.背景: 最近把之前做的一个HR招聘信息管理工具翻新了下,有需要的朋友可以自取,主要想解决的问题是多人在跟进人员招聘的时候信息的不对称,这样下来的就可以及时的看到整个 ...

  4. Python趣味入门9:函数是你走过的套路,详解函数、调用、参数及返回值

    1.概念 琼恩·雪诺当上守夜人的司令后,为训练士兵对付僵尸兵团,把成功斩杀僵尸的一系列动作编排成了"葵花宝典剑法",这就是函数.相似,在计算机世界,一系列前后连续的计算机语句组合在 ...

  5. 论文解读(LA-GNN)《Local Augmentation for Graph Neural Networks》

    论文信息 论文标题:Local Augmentation for Graph Neural Networks论文作者:Songtao Liu, Hanze Dong, Lanqing Li, Ting ...

  6. 是时候为Spring Boot 3.0做准备了

    2018年2月28日Spring Boot进入2.0时代,距今已经超过4年了. 2022 年 11 月 Spring Boot 3.0 将正式发布,它将基于 Spring Framework 6.0, ...

  7. java中的final与可变类型、不可变类型的关系

    如果你对final和不可变类型的概念与区别有疑问的话,可以打开这篇文章.希望我的解答可以帮到您! 1.不可变类型: 什么是可变类型,什么是不可变类型呢? 首先我们看一下下面的这行代码: String ...

  8. element-ui table组件使用v-if时的问题

    element-ui项目中经常遇到需要使用v-if指令来根据情况动态显示隐藏某些列情况,这时就会出现滚动条样式异常.列错乱.列宽错乱等问题 解决办法:在el-table上添加:key="Ma ...

  9. WindowsServer评估版转为正式版并激活

    更新记录 本文迁移自Panda666原博客,原发布时间:2021年5月16日. 一般从官网下载的Windows Server版本都是评估试用版本.这时候想转为正式版本,就需要使用转换激活代码.请参照不 ...

  10. BI与SaaS碰撞,让数据处理更加轻松(下)

    背景 在上篇内容中,我们从SaaS各种功能的角度为大家介绍了在数据处理中SaaS的巨大价值,而本次我们将用实例将为大家展示SaaS与BI间的碰撞又会产生怎样的火花. BI与SaaS集成示例 通常BI分 ...