AS3 Frogger像素完美碰撞



我已经创建了一个简单的AS3青蛙游戏,并使用. hittestobject来测试青蛙是否碰到了任何障碍。这是无效的,因为青蛙击中的物体根本没有接触到它。我是AS3的新手,不知道从哪里开始编写代码。任何帮助将不胜感激!

包{

import flash.display.*;
import flash.events.*;
import flash.utils.*;
import flash.ui.*;
import flash.events.Event;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.utils.Timer;
import flash.display.BitmapData;
import flash.display.Bitmap;
    public class Main extends MovieClip 
    {
        //set variables
        public var frog_spriteInstance:frog_sprite;
        public var safeZoneInstance1 : safeZone;
        public var safeZoneInstance2: safeZone;
        public var safeZoneInstance3 : safeZone;
        public var whitecar : car1;
        public var whitecar1 : car1; 
        public var whitecar2 : car1; 
        public var truck1 : truck_sprite;
        public var truck2: truck_sprite;
        public var redcar : car_sprite;
        public var redcar2 : car_sprite;
        public var redcar3 : car_sprite;
        public var log1 : log_sprite;
        public var log2 : log_sprite;
        public var log3 : log_sprite;
        public var letters : Letters;
        public var letters2 : Letters_2;
        public var letters3 : Letters_3;
        public var letters4 : Letters_4;
        public var health : HealthBar;
        public var firstletter : firstLetter;
        public var secondletter : secondLetter;
        public var thirdletter : thirdLetter;
        public var fourthletter : fourthLetter;
        var mysound:Sound = new (mySound); 

        public function Main()
        {
            // constructor code
            safeZoneInstance1 = new safeZone();
            stage.addChild(safeZoneInstance1);
            safeZoneInstance1.x = 300;
            safeZoneInstance1.y=545
            safeZoneInstance2 = new safeZone();
            stage.addChild(safeZoneInstance2);
            safeZoneInstance2.x = 300;
            safeZoneInstance2.y=300
            safeZoneInstance3 = new safeZone();
            stage.addChild(safeZoneInstance3);
            safeZoneInstance3.x = 300;
            safeZoneInstance3.y=100
            whitecar = new car1();
            stage.addChild(whitecar);
            whitecar.x = 300;
            whitecar.y = 500
            whitecar1 = new car1();
            stage.addChild(whitecar1);
            whitecar1.x = 550;
            whitecar1.y = 480
            whitecar2 = new car1();
            stage.addChild(whitecar2);
            whitecar2.x = 50;
            whitecar2.y = 480
            truck1 = new truck_sprite();
            stage.addChild (truck1);
            truck1.x = 1000;
            truck1.y = 430
            truck2 = new truck_sprite();
            stage.addChild (truck2);
            truck2.x = 300;
            truck2.y = 430
            redcar = new car_sprite();
            stage.addChild (redcar);
            redcar.x = 300;
            redcar.y = 340
            redcar2 = new car_sprite();
            stage.addChild (redcar2);
            redcar2.x = 100;
            redcar2.y = 375
            redcar3 = new car_sprite();
            stage.addChild (redcar3);
            redcar3.x = 500;
            redcar3.y = 375
            log1 = new log_sprite();
            stage.addChild(log1);
            log1.x = 300;
            log1.y = 230
            log2 = new log_sprite();
            stage.addChild(log2);
            log2.x = 100;
            log2.y = 150

            log3 = new log_sprite();
            stage.addChild(log3);
            log3.x = 500;
            log3.y = 150
            letters = new Letters();
            letters.x = randomRange(100,500) ;
            letters.y = randomRange(100,500);
            stage.addChild(letters); 
            letters2 = new Letters_2();
            letters2.x = randomRange(100,500) ;
            letters2.y = randomRange(100,500);
            stage.addChild(letters2); 
            letters3 = new Letters_3();
            letters3.x = randomRange(100,500) ;
            letters3.y = randomRange(100,500);
            stage.addChild(letters3); 
            letters4 = new Letters_4();
            letters4.x = randomRange(100,500) ;
            letters4.y = randomRange(100,500);
            stage.addChild(letters4); 
            frog_spriteInstance = new frog_sprite();
            stage.addChild(frog_spriteInstance);  
            frog_spriteInstance.x=300; 
            frog_spriteInstance.y=550;
            health = new HealthBar();
            stage.addChild(health);
            health.x = 130;
            health.y = 20;
            health.width = 100;
            stage.addEventListener(KeyboardEvent.KEY_DOWN, moveFrog);
            stage.addEventListener(Event.ENTER_FRAME, movecars); 
            stage.addEventListener(Event.ENTER_FRAME, movetrucks);
            stage.addEventListener(Event.ENTER_FRAME, moveredcars);
            stage.addEventListener(Event.ENTER_FRAME, movelogs);
            stage.addEventListener(Event.ENTER_FRAME,checkforcollision);
            mysound.play();
        }
        public function moveFrog(e:KeyboardEvent)
        {   
           // get the key pressed and then move the player
            {
                if (e.keyCode == Keyboard.UP)
                {
                    frog_spriteInstance.rotation = 0;
                    frog_spriteInstance.y -= 50;
                }
                if (e.keyCode == Keyboard.DOWN)
                {
                    frog_spriteInstance.rotation = 180;
                    frog_spriteInstance.y += 50;
                }
                if (e.keyCode == Keyboard.LEFT)
                {
                    frog_spriteInstance.rotation = -90;
                    frog_spriteInstance.x -= 50;
                }
                if (e.keyCode == Keyboard.RIGHT)
                {
                    frog_spriteInstance.rotation = 90;
                    frog_spriteInstance.x += 50;
                }
            }
        }
        function movecars(event:Event)  
        {  
            //move cars across screen and when they disappear, reappear at the other side
            whitecar.x -= 3;  
            if (whitecar.x<-100){
            whitecar.x=650;
            }  
            whitecar1.x -= 3;  
            if (whitecar1.x<-100){
            whitecar1.x=650;
            } 
            whitecar2.x -= 3;  
            if (whitecar2.x<-100){
            whitecar2.x=650;
            } 
        }
        function movelogs(event:Event)  
        {  
            //move logs across screen and when they disappear, reappear at the other side
            log1.x -= 5;  
            if (log1.x<-100){
            log1.x=650;
            }  
            log2.x -= 5;  
            if (log2.x<-100){
            log2.x=650;
            } 
            log3.x -= 5;  
            if (log3.x<-100){
            log3.x=650;
            } 
        }
        function movetrucks(event:Event)
        {
            //move trucks across screen and when they disappear, reappear at the other side
            truck1.x +=3;
        if (truck1.x>650){
            truck1.x=-100;
            }
            truck2.x +=3;
        if (truck2.x>650){
            truck2.x=-100;
            }
        }
        function moveredcars(event:Event)
        {
            //move red cars across screen and when they disappear, reappear at the other side
            redcar.x +=3;
        if (redcar.x>650){
            redcar.x=-100;
            }
            redcar2.x +=3;
        if (redcar2.x>650){
            redcar2.x=-100;
            }
            redcar3.x +=3;
        if (redcar3.x>650){
            redcar3.x=-100;
            }
        }
        function checkforcollision(event:Event)
        {
            //check for collisions
            if (frog_spriteInstance.hitTestObject(log1) || (frog_spriteInstance.hitTestObject(log2) || (frog_spriteInstance.hitTestObject(log3) || (frog_spriteInstance.hitTestObject(whitecar) || (frog_spriteInstance.hitTestObject(whitecar1) || (frog_spriteInstance.hitTestObject(whitecar2) || (frog_spriteInstance.hitTestObject(log2) || (frog_spriteInstance.hitTestObject(truck1) || (frog_spriteInstance.hitTestObject(truck2) || (frog_spriteInstance.hitTestObject(redcar) || (frog_spriteInstance.hitTestObject(redcar2) || (frog_spriteInstance.hitTestObject(redcar3))))))))))))){
            //reset frog if hits an obstacle
            stage.addChild(frog_spriteInstance);  
            frog_spriteInstance.x=300; 
            frog_spriteInstance.y=550;
            //reduce health bar
            health.width -= 10;
            }
            //remove event listeners when health is empty
            if (health.width == 0){
            stage.removeEventListener(Event.ENTER_FRAME, movecars);
            stage.removeEventListener(KeyboardEvent.KEY_DOWN, moveFrog);
            stage.removeEventListener(Event.ENTER_FRAME, movetrucks);
            stage.removeEventListener(Event.ENTER_FRAME, moveredcars);
            stage.removeEventListener(Event.ENTER_FRAME, movelogs);
            }
            //add letters to bottom of screen when hit correctly
            if (frog_spriteInstance.hitTestObject(letters)){
                stage.addChild(frog_spriteInstance);  
                frog_spriteInstance.x=300; 
                frog_spriteInstance.y=550;
                stage.removeChild(letters);
                firstletter = new firstLetter();
                stage.addChild(firstletter);
                firstletter.x=345; 
                firstletter.y=600; 
            }
            if (frog_spriteInstance.hitTestObject(letters2)){
                stage.addChild(frog_spriteInstance);  
                frog_spriteInstance.x=300; 
                frog_spriteInstance.y=550;
                stage.removeChild(letters2);
                secondletter = new secondLetter();
                stage.addChild(secondletter);
                secondletter.x=206; 
                secondletter.y=600; 
            }
            if (frog_spriteInstance.hitTestObject(letters3)){
                stage.addChild(frog_spriteInstance);  
                frog_spriteInstance.x=300; 
                frog_spriteInstance.y=550;
                stage.removeChild(letters3);
                thirdletter = new thirdLetter();
                stage.addChild(thirdletter);
                thirdletter.x=273; 
                thirdletter.y=600; 
            }
            if (frog_spriteInstance.hitTestObject(letters4)){
                stage.addChild(frog_spriteInstance);  
                frog_spriteInstance.x=300; 
                frog_spriteInstance.y=550;
                stage.removeChild(letters4);
                health.width -= 10;
                fourthletter = new fourthLetter();
                stage.addChild(fourthletter);
                fourthletter.x=25; 
                fourthletter.y=620; 
            }
        }
        function randomRange(minNum:Number, maxNum:Number):Number 
        {
            //random generator for letter positioning
            return (Math.floor(Math.random() * (maxNum - minNum + 1)) + minNum);
        }
   }

}

我的代码也很不可靠,所以任何改进的建议都是非常欢迎的。

要从两个任意显示对象执行像素完美命中测试,您必须将它们绘制为位图并使用BitmapData/hitTest()

下面是一个通用函数:

function hitTestShapes(object1:DisplayObject, object2:DisplayObject, threshold:uint = 1):Boolean {
    var bounds1:Rectangle = object1.getBounds(object1.parent);
    var matrix1:Matrix = object1.transform.matrix;
    matrix1.tx = object1.x - bounds1.x;
    matrix1.ty = object1.y - bounds1.y;
    var bmp1:BitmapData = new BitmapData(bounds1.width, bounds1.height, true, 0);
    bmp1.draw(object1, matrix1);
    var bounds2:Rectangle = object2.getBounds(object2.parent);
    var matrix2:Matrix = object2.transform.matrix;
    matrix2.tx = object2.x - bounds2.x;
    matrix2.ty = object2.y - bounds2.y;
    var bmp2:BitmapData = new BitmapData(bounds2.width, bounds2.height, true, 0);
    bmp2.draw(object2, matrix2);
    return bmp1.hitTest(bounds1.topLeft, threshold, bmp2, bounds2.topLeft, threshold);
}

注意,不过,绘制到位图是相当慢的,所以要小心不要过度使用这种功能,否则你会有性能问题。事实上,首先使用hitTestObject()是一个好主意,它非常快并检测边界框交叉点,然后只调用hitTestShapes()来完善您的检查。换句话说:

if (frog_spriteInstance.hitTestObject(log1) && hitTestShapes(frog_spriteInstance, log1)) { }

对于代码的建议,通过数组、循环和函数有很多重复数据删除的可能性。例如,与其将所有对象定义为单独的变量,不如将它们全部存储在数组(或向量)中:

public var safeZones:Array = [];
public var obstacles:Array = [];
public var letters:Array = [];

要填充数组,您可以将值压入其中,并使用一个函数来合并所有重复的对象设置代码:

(代码约定注意:类名使用"UpperCamelCase")

public function Main(){
    addSafeZone(300, 545);
    addSafeZone(300, 300);
    addSafeZone(300, 100);
    addObstacle(WhiteCar, 300, 500);
    addObstacle(WhiteCar, 550, 480);
    addObstacle(WhiteCar, 50, 480);
    addObstacle(Truck, 1000, 430);
    addObstacle(Truck, 300, 430);
    addObstacle(RedCar, 300, 340);
    addObstacle(RedCar, 100, 375);
    addObstacle(RedCar, 500, 375);
    addObstacle(Log, 300, 230);
    addObstacle(Log, 100, 150);
    addObstacle(Log, 500, 150);
    addRandomLetters(Letters_1);
    addRandomLetters(Letters_2);
    addRandomLetters(Letters_3);
    addRandomLetters(Letters_4);
}
private function addSafeZone(x:Number, y:Number):void {
    var safeZone:SafeZone = new SafeZone();
    stage.addChild(safeZone);
    safeZone.x = x;
    safeZone.y = y
    safeZones.push(safeZone);
}
private function addObstacle(spriteClass:Class, x:Number, y:Number):void {
    var obstacle:Sprite = new spriteClass();
    stage.addChild(obstacle);
    obstacle.x = x;
    obstacle.y = y
    obstacles.push(obstacle);
}
private function addRandomLetters(lettersClass:Class):void {
    var lettersSprite:Sprite = new lettersClass();
    lettersSprite.x = randomRange(100, 500);
    lettersSprite.y = randomRange(100, 500);
    stage.addChild(lettersSprite); 
    letters.push(lettersSprite);
}

现在可以遍历数组来执行所有操作。例如,检查是否命中任何障碍物:

for each(var obstacle:DisplayObject in obstacles){
    if(frog.hitTestObject(obstacle) && hitTestShapes(frog, obstacle)){
        // The frog hit an obstacle!
    }
}

你也可以把我们所有的"移动"函数组合成一个,它根据每个障碍物的类型移动它们:

private function moveObstacles(e:Event):void {
    for each(var obstacle in obstacles){
        if(obstacle is WhiteCar){
            obstacle.x -= 3;
        }
        else if(obstacle is RedCar){
            obstacle.x += 3;
        }
        else if(obstacle is Truck){
            obstacle.x += 3;
        }
        else if(obstacle is Log){
            obstacle.x -= 5;
        }
        if(obstacle.x < -100){
            obstacle.x = 650;
        }
        else if(obstacle.x > 650){
            obstacle.x = -100;
        }
    }
}

最后,您实际上只需要一个ENTER_FRAME处理程序。从这里调用你想要的任何函数。添加多个ENTER_FRAME处理程序可能会变得难以管理。例如,只需这样做:

addEventListener(Event.ENTER_FRAME, update);
private function update(e:Event):void {
    moveObstacles();
    doOtherStuff();
    anythingYouNeedToDo();
}

这样你只需要removeEventListener(Event.ENTER_FRAME, update)来停止游戏,而不是一堆ENTER_FRAME处理程序。

我还没有测试过这些代码,但是您可以得到大致的想法。如果你有任何问题,请告诉我,我可以帮忙。

最新更新