[英]An analogue of the game "Worms". Physics. as3
請幫忙寫一個彈丸離地反彈的函數。 我如何找到碰撞的角度,反射角度應該是多少或至少了解碰撞點?
package {
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.geom.Point;
import flash.geom.Matrix;
import flash.events.Event;
import flash.events.MouseEvent;
public class worms extends Sprite {
public var terrain_bmpd=new BitmapData(550,200,true,0xFF00FF00);//This is the Bitmap of the terrain
public var terrain_bmp=new Bitmap(terrain_bmpd);//and this the BitmapData
public var character=new Sprite();//The character will work as a worm
public var hole=new Sprite();//That's the hole we need
public var hole_matrix:Matrix;//The hole_matrix is used to set the position of the hole
public var left_foot:Point;
public var right_foot:Point;//These are the feet of the character. We will use it to check collisions
public function worms() {
draw_objects();//This function draws the character, the terrain and the hole.
stage.addEventListener(Event.ENTER_FRAME,fall);
}
public function fall(e:Event) {
/*This function will move down the character if there isn't a collision
between the terrain and the "feet" of the character*/
for (var i:int=0; i<10; i++) {//We want to check every pixel if there's acollision, so we won't move the character 10 pixels all at once
left_foot=new Point(character.x-5,character.y+10);
right_foot=new Point(character.x+5,character.y+10);
if (!(terrain_bmpd.hitTest(new
Point(terrain_bmp.x,terrain_bmp.y),0x01,left_foot))&&!(terrain_bmpd.hitTest(new Point(terrain_bmp.x,terrain_bmp.y),0x01,right_foot))) {
character.y++;//If there aren't any collisions, make the character fall one pixel
}
}
}
public function draw_objects() {
terrain_bmp.y=200;//The terrain shouldn't be at the top of the stage!
stage.addChild(terrain_bmp);//We can make the terrain visible
character.graphics.beginFill(0x0000FF);//Let's draw the character. It will be a blue rectangle.
character.graphics.drawRect(-5,-10,10,20);
character.x=250;
stage.addChild(character);
hole.graphics.beginFill(0x000000);//Now we draw the hole. It doesn't matter the colour.
hole.graphics.drawCircle(0,0,30);
}
}
}
這有幾個部分,似乎您真的不知道從哪里開始。
就像其他人提到的那樣,您的對象(彈丸、角色等)的運動應由向量表示,即 x 和 y 速度。 (一個Point
可以代表一個向量。)
接下來,要像您一樣檢測基於像素的地形上的碰撞角度,您可以在對象周圍的半徑內進行一系列點(像素)命中測試。 這將為您提供一組命中點,您將其定義為來自對象中心的向量。 平均向量,你有你的碰撞角度。
這是我用來執行此操作的函數:
/**
* Test for a hit against a shape based on a point and radius,
* returns the angle of the hit or NaN if no hit.
* Like hitTestPoint, xPos and yPos must be in stage coordinates.
*/
function hitTestAngle(shape:Sprite, xPos:Number, yPos:Number, radius:Number, samples:uint = 90):Number {
const PI2:Number = Math.PI * 2, SAMPLE:Number = 1 / samples;
var dx:Number, dy:Number, a:Number, tx:Number = 0, ty:Number = 0, hits:int = 0;
var i:int = samples;
while(i--){
a = PI2 * (i * SAMPLE);
dx = radius * Math.cos(a);
dy = radius * Math.sin(a);
if(shape.hitTestPoint(xPos + dx, yPos + dy, true)){
hits++;
tx += dx;
ty += dy;
}
}
if(!hits)
return NaN;
return Math.atan2(ty, tx) * (180 / Math.PI);
}
這使用hitTestPoint()
但由於您的地形是BitmapData
您可以只使用getPixel32()
並檢查 alpha 值。
您還可以使用Collision Detection Kit ,它在幕后使用類似的方法,並具有許多額外的功能。
一旦你有了碰撞的角度,你就可以定義一個垂直向量作為碰撞表面來反映射彈的向量。
這應該讓你開始。
平坦、水平地面:
//Check next movementstep
if((vel_y + pos_y) > terrainBottom) {
vel_y = -vel_y*DampingFactor;
}
對於一般情況,您需要使用三角函數將 vel_x, vel_y 轉換為上述情況。
與之前的答案一樣,使用 vel_x 和 vel_y 以矢量形式表示角色的運動。 使用這些值在每次迭代時增加 x 和 y 坐標。 在您的示例中,您使用 vel_x = 0, vel_y = 1,因為您每次都將 y 坐標增加 1。
如果一個表面有一個從水平方向逆時針測量的角度 A,那么 x_vel 和 y_vel 在表面上反彈(反射)后將分別是 x_vel.cos2A + y_vel.sin2A 和 x_vel.sin2A - y_vel.cos2A。 要了解這是如何得出的,請參閱Planetmath
這是為了完全彈性碰撞,即碰撞時沒有速度損失。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.