AS3 中的球反弹问题

Ball bounce issue in AS3

[编辑]

我当时真的很傻,现在一切正常。 所以忘记这个虚拟问题吧!

主剪辑的旋转是个大错误

我通过添加一个名为 _rota 的 var getter 和 setter 来更改它。

我不必旋转剪辑,只需在其中放置另一个 Sprite,因此我可以使用一个简单的函数将子 Sprite 放置在正确的方向。 所以我避免了所有这些循环...

我错了SRY。

我刚刚添加了一个 Sprite,它具有 Main Sprite 的旋转。 改变主 Sprite 的旋转是这个问题的原因...... 所以,谢谢你,忘记这个不清楚的问题!!! :)

private function drawLine():void{
        if(!clip){
            clip = new Sprite();
            addChild(clip);
        }
        var g:Graphics = clip.graphics;
        g.clear();
        g.lineStyle(1,0xffffff,1);
        g.beginFill(0xffffff,1);
        g.drawCircle(Math.sin(rota)*this.width/4,Math.cos(rota)*this.height/4,3);
        g.endFill();
    }

我正在更改剪辑的旋转 属性,所以很有用 现在我有一个很好的结果。 已解决...

再次抱歉...

如您所见,粒子现在设置在正确的方向,我没有更多的 hitTest 问题...

粒子现在沿着白点指示的方向移动。

[/edit]

我首先想到的是,您可能会两次修改 xy 属性的位置。

如果你 运行 一次逻辑,并存储你的方向性,那么你应该能够一次性更新你的球的位置。

将您的 moveBall 函数替换为以下...

private var h:int = 1;
private var v:int = 1;
public function moveBall(e:Event):void {
    speedx = Math.sin(deg2rad(rotation+90))*speed;
    speedy = Math.cos(deg2rad(rotation+90))*speed;

    if (x + radius + (speedx * h) > this.loaderInfo.width || (x + (speedx * h) - radius < 0)) {
        h *= -1;
    }

    if (y + radius + (speedy * v) > this.loaderInfo.height || (y + (speedx * v) - radius < 0)) {
        v *= -1;
    }

    this.x += (speedx * h);
    this.y += (speedy * v);
}

因为我需要在 Ball 实例更改时将 Sprite 设置为正确的方向 "pseudo rotation"(我在这里避免使用 hitTest 功能)...

我现在有两个 classes... 你觉得我是在代码的光明面搜索还是完全不清楚? ;)

这只是一个测试,我已经几年没有花时间写代码了。 所以这个测试只是为了复习一些三角学的基础知识...... 不要犹豫,如果我错了,请不要客气!

我的新 class 主要 :

package com
{
import com.display.Ball;

import flash.display.Graphics;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;

[SWF(width = "400", height = "300", frameRate = "60", backgroundColor = "#dddddd")]
public class Main extends MovieClip
{
    private var b1:Ball;
    private var b2:Ball;
    private var b3:Ball;
    private var b4:Ball;
    private var b5:Ball;
    private var testClip:Sprite;
    private const ANGLE_TOP_LEFT:int=135;
    private const ANGLE_BOTTOM_LEFT:int=-135;
    private const ANGLE_TOP_RIGHT:int=45;
    private const ANGLE_BOTTOM_RIGHT:int=-45;

    public function Main()
    {
        stage.align = StageAlign.TOP_LEFT;
        stage.scaleMode = StageScaleMode.NO_SCALE;
        trace("stageSize = " + getStageSize() + ", fps = " + stage.frameRate);
        drawlineGuides();
        addBalls();
        stage.addEventListener(Event.RESIZE,onStageResize);
    }
    private function addBalls():void{
        b1 = new Ball(500/2,250/2,10);
        addChild(b1);
        b1.color = 0x6666cc;
        b1.rota = 135;
        b1.drawBall();
        b1.move(5); 

        b2 = new Ball(100,100,10);
        addChild(b2);
        b2.color = 0xff9900;
        b2.rota = -110;
        b2.drawBall();
        b2.move(4);

        b3 = new Ball(50,80,10);
        addChild(b3);
        b3.color = 0xff0000;
        b3.rota = 60;
        b3.drawBall();
        b3.move(3);

        b4 = new Ball(75,20,10);
        addChild(b4);
        b4.color = 0x00aa00;
        b4.rota = 10;
        b4.drawBall();
        b4.move(4);

        b5 = new Ball(125,130,10);
        addChild(b5);
        b5.color = 0x8457a2;
        b5.rota = -45;
        b5.drawBall();
        b5.move(4);

        stage.addEventListener(MouseEvent.MOUSE_DOWN,b1.pauseResume);
        stage.addEventListener(MouseEvent.MOUSE_DOWN,b2.pauseResume);
        stage.addEventListener(MouseEvent.MOUSE_DOWN,b3.pauseResume);
        stage.addEventListener(MouseEvent.MOUSE_DOWN,b4.pauseResume);
        stage.addEventListener(MouseEvent.MOUSE_DOWN,b5.pauseResume);
    }
    private function rotate(e:Event):void{
        testClip.rotation = b2.rotation-45;
    }
    private function getStageSize():Point{
        var p:Point= new Point(stage.stageWidth,stage.stageHeight);
        return p;
    }
    private function drawlineGuides():void{
        var g:Graphics = this.graphics;
        g.clear();
        g.lineStyle(1,0x000000,1);
        g.moveTo(0,stage.stageHeight/2);
        g.lineTo(stage.stageWidth,stage.stageHeight/2);
        g.moveTo(stage.stageWidth/2,0);
        g.lineTo(stage.stageWidth/2,stage.stageHeight);
    }
    private function onStageResize(e:Event):void{
        drawlineGuides();
    }
}
}

这是我的新 class 球:

package com.display
{
/* this import is optionnal
if you want to run this class without the BongSound instance
comment all lines where the var bSound is called
*/
//import com.media.sound.BongSound;

import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.media.Sound;

public class Ball extends Sprite
{
    private var _radius:int;
    private var _rotation:Number;
    private var _color:int;
    private var _g:Graphics;
    private var _g2:Graphics;
    private var _speed:Number;
    private var speedx:Number;
    private var speedy:Number;
    public var rota:Number;
    private var smallCircle:Sprite;
    private var rendered:Boolean = false;
    public var paused:Boolean = false;
    private const ZERO:uint = 0;
    //private var bSound:BongSound;
    /**
     * Ball(posx:Number,posy:Number,radius:uint)<br/>
     * this constructor create an instance of a bouncing ball<br/>
     * the posx and posy must be included in the range of the defined stageWidth and stageHeight!<br/>
     * Otherwise, the ball will be placed in the stage range.
     */
    public function Ball(posx:Number,posy:Number,radius:uint)
    {
        //bSound = new BongSound();
        smallCircle = new Sprite();
        this.addChild(smallCircle);
        this._radius = radius;
        this.x = posx;
        this.y = posy;
        _g = this.graphics;
        _g2 = smallCircle.graphics;
    }
    private function checkStageSize():void{
        if(this.x + radius + speedx >= this.stage.stageWidth){
            this.x = this.stage.stageWidth - this.width;
        }
        if(this.y + radius + speedy >= this.stage.stageHeight){
            this.y = this.stage.stageHeight - this.height;
        }
        if(this.x - radius + speedx <= ZERO){
            this.x = this.width;
        }
        if(this.y - radius + speedy <= ZERO){
            this.y = this.height;
        }
    }
    public function get speed():Number
    {
        return _speed;
    }
    public function set speed(value:Number):void
    {
        _speed = value;
    }
    public function get color():int
    {
        return _color;
    }
    public function set color(value:int):void
    {
        _color = value;
    }
    public function get radius():int
    {
        return _radius;
    }
    public function set radius(value:int):void
    {
        _radius = value;
    }
    /**
     * drawBall()<br/>
     * this function draws the main Ball Object
     */
    public function drawBall():void
    {
        _g.clear();
        _g.lineStyle(1,0x666666,1);
        _g.beginFill(_color,1);
        _g.drawCircle(0,0,this._radius);
        _g.endFill();
        _g.lineStyle(1,0x666666,1);
        _g.beginFill(0xffffff,1);
        _g.endFill();
    }
    /**
     * drawPoint()<br/>
     * this function draws the Point Object wich is placed in the direction/rotation of the main Ball instance.
     */
    public function drawPoint():void{
        _g2.clear();
        _g2.lineStyle(1,0x666666,1);
        _g2.beginFill(0xffffff,1);
        _g2.drawCircle(ZERO, ZERO, this._radius/2);
        smallCircle.x = Math.sin(deg2rad(rota+90))*this.radius/2;
        smallCircle.y = Math.cos(deg2rad(rota+90))*this.radius/2;
        _g2.endFill();
    }
    /**
     * move(speed:Number):void<br/>
     * this function set the speed and makes the Ball move.<br/>
     * The displace function is called when an ENTER_FRAME event is triggered.
     */
    public function move(speed:Number):void{
        this.speed = speed;
        this.addEventListener(Event.ENTER_FRAME,displace);
    }
    /**
     * getRota():Number<br/>
     * this function returns the rotation of the Ball instance.<br/>
     * the rotation is returned in degrees.
     */
    public function getRota():Number{
        return rad2deg(Math.atan2(speedy,speedx));
    }
    /**
     * pauseResume(e:MouseEvent):void
     * Pause or resume movement.
     */
    public function pauseResume(e:MouseEvent):void{
        switch(paused){
            case false:
                this.removeEventListener(Event.ENTER_FRAME,displace);
                paused = true;
                break;
            case true:
                this.addEventListener(Event.ENTER_FRAME,displace);
                paused = false;
                break;
        }
    }
    /**
     * checkBounds():void<br/>
     * <p>
     * this function plays a Sound when the Ball instance hit the bounds.<br/>
     * the rota variable is updated (even if the rotation of the Ball instance don't change).<br/>
     * If the stage is resized, a call to checkStageSize() set the positions x & y in the bounds of the Stage.
     * </p>
     * @see checkStageSize()
     */
    private function checkBounds():void{
        if(this.x + radius + speedx >= this.stage.stageWidth){
            //bSound.play();
            rota = rad2deg(Math.atan2(-speedy,-speedx));
        }
        if(this.y + radius + speedy >= this.stage.stageHeight){
            //bSound.play();
            rota = rad2deg(Math.atan2(speedy,speedx));
        }
        if(this.x - radius + speedx <= ZERO){
            //bSound.play();
            rota = rad2deg(Math.atan2(-speedy,-speedx));
        }
        if(this.y - radius + speedy <= ZERO){
            //bSound.play();
            rota = rad2deg(Math.atan2(speedy,speedx));
        }
        checkStageSize();
    }
    /**
     * <p>
     * displace(e:Event):void
     * displace the ball and calls drawPoint to place the sub-Sprite depending of the "rotation" of the Ball instance.</p>
     * @see #drawPoint()
     * @see #checkBounds()
     */
    private function displace(e:Event):void{
        checkBounds();
        speedx = Math.sin(deg2rad(rota+90))*speed;
        speedy = Math.cos(deg2rad(rota+90))*speed;
        this.x += speedx;
        this.y += speedy;
        drawPoint();
    }
    public function deg2rad(value:Number):Number{
        return value/180*Math.PI;
    }
    public function rad2deg(value:Number):Number{
        return value*180/Math.PI;
    }

}
}

打印屏幕:

现在即使在调整舞台大小时也可以继续移动,避免了我过去遇到的问题...