游戏“蠕虫”的类比。物理。 AS3

时间:2015-09-24 20:10:47

标签: actionscript-3

请帮助写下弹丸从地面反弹的功能。如何找到碰撞的角度,反射角应该是什么,或者至少要了解碰撞点?

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);
        }
    }
}

3 个答案:

答案 0 :(得分:1)

这有几个部分,看起来你真的不知道从哪里开始。

与其他人提到的一样,你的物体(抛射物,角色等)的运动应该用vector表示,即x和y速度。 (A Point可以表示向量。)

接下来,要像你一样检测基于像素的地形上的碰撞角度,你可以在radius around the object中进行一系列点(像素)命中测试。这将为您提供一组生命点,您可以从对象的中心定义为矢量。 Average the vectors and you have your collision angle.

这是我以前执行此操作的功能:

/**
 * 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()check the alpha value

你也可以使用Collision Detection Kit,它使用类似的方法,带有一堆额外的功能。

一旦有了碰撞角度,就可以将perpendicular vector定义为reflect the projectile's vector的碰撞面。

这应该让你开始。

答案 1 :(得分:0)

平坦的水平地面:

//Check next movementstep
if((vel_y + pos_y) > terrainBottom) {
   vel_y = -vel_y*DampingFactor;
}

对于一般情况,您需要使用三角函数将vel_x,vel_y转换为上面显示的情况。

答案 2 :(得分:0)

与上一个答案一样,使用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

这是一次完美的弹性碰撞,即撞击时没有速度损失。