Actionscript 3 AS3中的球反弹问题
[编辑] 我真的很笨,现在一切都好了。 所以忘掉这个愚蠢的问题吧 主剪辑的旋转是一个很大的错误 我改变了这一点,添加了一个名为_rota的变量,其中包含getter和setter 我不必旋转剪辑,只需在其中放置另一个精灵,这样我就可以使用一个简单的函数将子精灵放置在正确的方向上。 所以我避免了所有这些循环 我错了 我刚刚添加了一个具有主精灵旋转的精灵。 更改主精灵的旋转是导致此问题的原因。。。 所以,谢谢你,忘掉这个不清楚的问题!!!:) 我正在更改剪辑的旋转属性,因此它很有用 现在我有一个很好的结果。 解决了 再次抱歉 正如你所看到的,粒子现在被设置在正确的方向,我没有更多的命中问题 粒子现在正沿着白点显示的方向移动Actionscript 3 AS3中的球反弹问题,actionscript-3,trigonometry,bounce,Actionscript 3,Trigonometry,Bounce,[编辑] 我真的很笨,现在一切都好了。 所以忘掉这个愚蠢的问题吧 主剪辑的旋转是一个很大的错误 我改变了这一点,添加了一个名为_rota的变量,其中包含getter和setter 我不必旋转剪辑,只需在其中放置另一个精灵,这样我就可以使用一个简单的函数将子精灵放置在正确的方向上。 所以我避免了所有这些循环 我错了 我刚刚添加了一个具有主精灵旋转的精灵。 更改主精灵的旋转是导致此问题的原因。。。 所以,谢谢你,忘掉这个不清楚的问题!!!:) 我正在更改剪辑的旋转属性,因此它很有用 现在我有一个很好
[/edit]我看到的第一件事是,您可能会两次修改
x
和y
属性的位置
如果只运行一次逻辑,并存储方向性,那么您应该能够一次性更新球的位置
将您的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);
}
私有变量h:int=1;
私有变量v:int=1;
公共功能移动球(e:事件):无效{
速度x=数学sin(deg2rad(旋转+90))*速度;
速度=数学cos(deg2rad(旋转+90))*速度;
如果(x+半径+(速度x*h)>this.loaderInfo.width | |(x+(速度x*h)-半径<0)){
h*=-1;
}
如果(y+半径+(speedy*v)>this.loaderInfo.height | |(y+(speedx*v)-半径<0)){
v*=-1;
}
这个.x+=(速度x*h);
这个.y+=(x v);
}
当球实例发生变化时,我需要将精灵设置在正确的方向上,它是“伪旋转”(我在这里避免使用最击功能)
我现在有两门课。。。
你认为我是在代码的光明面上搜索还是完全不清楚?;)
这只是一个测试,几年来我没有花时间编写代码。
所以这次考试只是为了复习一些关于三角学的基础知识。。。
如果我错了,不要犹豫,要粗鲁
我的新班级:
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();
}
}
}
这是我的新班级舞会:
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;
}
}
}
package.com.display
{
/*此导入是可选的
如果要在不使用BongSound实例的情况下运行此类
注释调用var bSound的所有行
*/
//导入com.media.sound.BongSound;
导入flash.display.Graphics;
导入flash.display.Sprite;
导入flash.events.Event;
导入flash.events.MouseEvent;
导入flash.geom.Point;
导入flash.media.Sound;
公共类舞会延伸雪碧
{
私有变量半径:int;
私有变量旋转:数字;
私有变量颜色:int;
私有变量:图形;
私有变量g2:图形;
私有变量速度:数字;
私有var speedx:编号;
私家车:号码;
公共变量表:编号;
私人圈子:雪碧;
呈现的私有变量:布尔值=false;
公共变量暂停:布尔值=false;
私有常数0:uint=0;
//私人var bSound:BongSound;
/**
*球(位置:编号,位置:编号,半径:uint)
*此构造函数创建一个反弹球的实例
*posx和posy必须包含在定义的stageWidth和stageHeight的范围内!
*否则,球将被放置在舞台范围内。
*/
公共功能球(posx:Number,posy:Number,radius:uint)
{
//bSound=新的BongSound();
smallCircle=新精灵();
这个.addChild(smallCircle);
这个。_半径=半径;
这个.x=posx;
这个.y=posy;
_g=这是图形;
_g2=小圆。图形;
}
私有函数checkStageSize():void{
如果(此.x+半径+速度x>=此.stage.stageWidth){
this.x=this.stage.stageWidth-this.width;
}
如果(此.y+半径+速度>=此.stage.stageHeight){
this.y=this.stage.stageHeight-this.height;
}
如果(这个.x-radius+speedx如果你在主类中将旋转设置为60,如下所示:b1.rotation=60;你会遇到同样的问题…哇,我完全忽略了你旋转它的事实。我会用一点解决方案来修改答案。现在一切都很好。对于那些重复的编辑,我很抱歉。代码清晰、高效且d跑得更快。这就是为什么我投票支持你的答案,即使它不能一眼解决我的问题。所以你不需要尝试寻找另一个答案。我错了…请原谅我。我希望“伪旋转”的含义在这种情况下有意义。(?如果你有时间,你能测试这两个类吗(库中没有任何元素)。请告诉我我看的方向是否正确,或者这是否仍然不清楚???非常感谢。这可能有助于理解我为什么在checkBounds()函数中使用Math.atan2,我希望。。
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;
}
}
}