用Java模拟游戏重力的实现(弹跳)
年末开了Java实训大作业
想了好几天决定选择马里奥小游戏
发现即使做出来但是跳跃功能是很“笨拙”的,和我们玩的游戏不一样,没有跳跃速度的快慢什么的,后来才知道这个叫做游戏里面重力的模拟。
组队做系统当然也有一分收获,但我觉得要做就做一个能让自己收获更大的,所以做游戏23333
发现重力模拟和碰撞检测都有很深的学问和算法在里面
那么先研究一下重力模拟!
我要先采集一下大概的信息哈
//****自定义绘图函数********************************* // 1.窗口贴图 // 2.计算小球速度,坐标以及判断是否碰到窗口下缘 void MyPaint(HDC hdc) { SelectObject(bufdc,bg); BitBlt(mdc,0,0,640,480,bufdc,0,0,SRCCOPY); SelectObject(bufdc,angrybird); BitBlt(mdc,x,y,60,60,bufdc,60,0,SRCAND); BitBlt(mdc,x,y,60,60,bufdc,0,0,SRCPAINT); BitBlt(hdc,0,0,640,480,mdc,0,0,SRCCOPY); x += vx; //计算X轴方向贴图坐标,每调用一次MyPiant(),x坐标就加上一个恒定不变的vx,相当于匀速运动 vy = vy + gy/20; //计算Y轴方向速度分量,vy随着每一次MyPiant()函数的调用就加上一个gy(重力加速度),因为50毫秒刷新一次 y += vy; //计算Y轴方向贴图坐标,每调用一次MyPiant(),y坐标就加上一个刚改变过后的vy,相当于加速运动 //判断是否触地,如果触碰到窗口边界,vy调整为相反方向 if(y >= rect.bottom-60) { y = rect.bottom - 60; vy = -vy; } tPre = GetTickCount(); //记录上次的绘图时间 }
重力系统涉及到的一些常见问题及解决方案如下:
1.给球体一个释放初速度,如何实现越向下运动且在接触边缘之前,竖直方向上的速度speedY越大的效果?
答案:可以在计时器中,每及时一次,竖直方向上的速度speedY自增一个固定值来实现,例如:speedY += 6;
2.球体接触地面(此例中指浏览器下边缘)后,如何实现速度反向效果?
答案:接触地面后,将方向速度置为当前速度的反方向即可,代码if (iW >= w||iW <= 0){speedX = -speedX;}if中条件表示如果超出运动范围,实现水平方向接触边缘后运动方向相反,代码if (iH >= h||iH <= 0){speedY = -speedY;}则表示Y方向接触边缘后速度变反。
3.球体接触地面反弹后,如何实现再次上升的高度低于上一次高度的效果?
答案:在接触地面后,速度变为负值,计时器开始执行下一个间隔,立即执行了speedY += 6,弹起速度立刻减小了6,其大小相对接触地面前一瞬间小,因此球体不会弹跳到原来的高度。
4.如何实现球体竖直方向上的速度绝对值越来越小直至逼近于0的效果?
答案:事实上,仅利用speedY += 6;此例中竖直方向上速度speedY不可能达到0,因为在该函数设置好了初速度的前提下,某一次落地速度不可能为6(通过后来打印速度每次执行结果可以确定),所以下一次执行不可能为0,那么究竟是怎样实现落到地面静止的效果的呢?实际上,当把speedY增加值设置为6时,当球体某一次落地瞬间它的速度是1,2,3,4,5中的任何一个值是,经加上6后反弹瞬时速度分别为-5,-4,-3,-2,-1,经过一个计时器周期(此例中为30毫秒),速度再加6立刻变为1,2,3,4,5,下一次速度变为-5,-4,-3,-2,-1......,由于speedY += 6在计时器的头处,因此最终结果将总是在加6之前,停留在-5,-4,-3,-2,-1.中的任何一个数值,且计时器始终处于动态,最终球体显示在底部。
5.当球体释放后,也具备有个横向速度speedX,如何使横向速度也逐渐减小值0?
答案:此例中不需要考虑x方向的碰撞,因此每次计时可将speedX乘以一个小于1的数,最终的speedX值将无限趋近于0,显示为静止。
当拖动窗口时如何实现不出现滚动条的效果?
答案:拖动后浏览器窗口后,对球体设置新的运动范围即可。
参考博客:https://blog.csdn.net/weixin_34151004/article/details/87964263
https://blog.csdn.net/weixin_36185028/article/details/53015790