제목 그대로입니다. 객체 재활용에 대해 가르침을 얻고자 이렇게 게시물을 작성해 봅니다.
사연은 이렇습니다;
런너 게임을 개발 중인데, 뭐가 꼬였는지 드래그를 하면 높은 확률로 애니메이션이 주춤거리며 제대로 동작하지 않는다는 거죠.
총 세 가지 애니메이션이 있습니다.
private Character m_Character;
private Character m_Character_Jump;
private Character m_Character_Roll;
차례대로
1. 디폴트 애니메이션 - 달리는 애니메이션( 이미지를 담고 있는 객체명 "m_Character" )
2. 위로 드래그 시 (Down - Move - Up 의 과정을 거쳐 실행) 폴짝 뛰는 애니메이션( "m_Character_Jump" )
3. 아래로 드래그 시 ( 동일한 MotionEvent를 거친 후 실행 ) 장애물 피해 구르는 애니메이션 ( "m_Character_Roll" )
짚히는 구석이 한두 군데가 아니지만 몇 가지로 간추려 보았습니다.
1. ( 각각 다른 객체를 사용하는 바람에 ) Update 과정에서 무언가가 꼬였다
2. Jump나 Roll 시에도 좌표값을 달리는(Run) 애니메이션 객체에서 받아온다는 점
3. 이미지의 좌표값을 지정해 주는 메소드 SetPostion의 사용이 부적절하다
대충 이 세 가지라고 생각합니다. 높은 확률로 잘못 짚었겠지만 말입니다 ㅠ ㅂ0
여기서 제가 알고 싶은 건 1번 문제의 답입니다사실 전부
혹시 여러 객체를 사용하려다 무언가가 꼬인 건 아닐까?
해서 하나의 객체를 재활용하면 될까 싶어 쓰던 객체에 그대로 new를 덮어 씌우기도 하고
먼저 null을 준 다음 다시 new를 줘 보기도 하고....
하지만 결과는 참담했습니다. 게임이 미친듯이 느려지는데다 애니메이션은 제대로 실행도 안 되더군요.
그나마도 LargeHeap을 안 줬으면 그대로 튕겼겠죠ㅠㅠㅠㅋㅋㅋ큐ㅜㅠㅠㅠㅠ
아마 new를 한 번만 줘야 하는데 조건문을 잘못 걸어 계속 new를 주게 되는 바람에 그렇지 싶습니다.
으아아아므아믄아ㅡ 미치겠습니다. 살려 주세요, 이걸로 한 달 동안 헤매니까 정신이 나갈 것 같습니다.
아니, 사실은 이걸로 한 달 동안 헤맨 건 아니지만 어쨌든 게임이 한 달 동안 진행이 없으니까 이젠 별별 게 다 걸리고 미칠 것 같습니다.
이걸 해결해야 굴러서 장애물을 피할 수 있는데 자꾸 주춤거리기만 하고ㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠ
그리고 장애물도 겹쳐서 나옵니다. 장애물이 생성될 때 일정 거리를 두고 생성이 되어야 하는데 그것도 안 되고ㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜ 사실 이게 가장 큰 문제입니다
@SuppressLint("UseValueOf")
@SuppressWarnings("unused")
public class GameState implements IState {
private GameView m_GameView;
private BackGround[] m_Background;
private long m_Timer;
private static int m_Timer_Count;
private Obstacle[] m_Obstacle;
long LastRegenObstacle;
public static int m_Obst_Number;
private static int Temp_XPos;
private static int Temp_YPos;
private static float Drag_Start_Position;
private static float Drag_End_Position;
private int Drag_Offset;
private boolean Action_Flag;
private boolean YPos_Flag;
private Character m_Character;
private Character m_Character_Jump;
private Character m_Character_Roll;
private Character[] m_Character_Life;
private boolean m_HitCheck;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
@SuppressWarnings("static-access")
@SuppressLint("UseValueOf")
@Override
public void Init() {
// TODO 자동 생성된 메소드 스텁
m_Background = new BackGround[2];
m_Background[0] = new BackGround();
m_Background[1] = new BackGround(true);
for(int i = 0; i < 2; i++)
{
m_Background[0].init();
m_Background[1].init();
}
Drag_Start_Position = 0;
Drag_End_Position = 0;
Drag_Offset = 0;
Action_Flag = true;
YPos_Flag = false;
m_Timer = System.currentTimeMillis();
m_Timer_Count = 0;
m_Obstacle = new Obstacle[5];
m_Obstacle[0] = new Obstacle_1();
m_Obstacle[1] = new Obstacle_2();
m_Obstacle[2] = new Obstacle_3();
m_Obstacle[3] = new Obstacle_4();
m_Obstacle[4] = new Obstacle_5();
m_Obstacle[0].setPosition(1300, 410);
m_Obstacle[1].setPosition(2000, 410);
m_Obstacle[2].setPosition(2400, 315);
m_Obstacle[3].setPosition(2800, 325);
m_Obstacle[4].setPosition(3200, 195);
LastRegenObstacle = System.currentTimeMillis();
Temp_XPos = 0;
Temp_YPos = 0;
m_Character_Life = new Character[3];
m_Character = new Character(AppManager.getInstance().
GetBitmap(com.play.R.drawable.sprite_run_600850));
m_Character_Jump = new Character(AppManager.getInstance().
GetBitmap(com.play.R.drawable.jump02));
m_Character_Jump.InSpriteData(m_Character_Jump.GetWidth(),
m_Character_Jump.GetHeight(), 1, 1);
m_Character_Roll = new Character(AppManager.getInstance().
GetBitmap(com.play.R.drawable.roll_sprite));
m_Character_Roll.InSpriteData(680, 655, 15, 6);
m_Character_Roll.setPosition(m_Character_Roll.GetDefaultXPos(),
m_Character_Roll.GetDefaultYPos() + 60);
// m_Character_Roll.m_BoundBox.set(m_Character_Roll.GetX() + 50, m_Character_Roll.GetY() + 200,
// m_Character_Roll.GetX() + 100, m_Character_Roll.GetY() + 400);
m_Character_Roll.m_BoundBox.set(50, 400, 150, 500);
for(int i = 0; i < m_Character.m_Life; i++)
{
m_Character_Life[i] = new Character(AppManager.getInstance().
GetBitmap(com.play.R.drawable.heart));
m_Character_Life[i].InSpriteData(300, 300, 1, 1);
m_Character_Life[i].setPosition((100 * i) + 50, 30);
}
m_HitCheck = false;
}
@Override
public void Destroy() {
// TODO 자동 생성된 메소드 스텁
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
@Override
public void Update() {
// TODO 자동 생성된 메소드 스텁
Log.v("Upate Log", "true!");
long GameTime = System.currentTimeMillis();
m_Character.m_BoundBox.set(m_Character.GetX() + 50, m_Character.GetY(),
m_Character.GetX() + m_Character.Get_Current_XPos(), m_Character.GetY() + m_Character.Get_Current_YPos() - 50);
if(Action_Flag == true)
m_Character.Update(GameTime);
else if(Action_Flag == false)
{
switch(Drag_Offset)
{
case 1:
{
// if(m_Character.Get_Current_YPos() <= 200)
// {
// YPos_Flag = false;
// }
if(YPos_Flag == false)
{
m_Character.SetYPos_Offset(5);
m_Character.Set_Current_YPos(m_Character.Get_Current_YPos()
+ m_Character.GetYPos_Offset());
//m_Character_Jump.Update(GameTime);
}
else if(YPos_Flag == true)
{
m_Character.SetYPos_Offset(-10);
m_Character.Set_Current_YPos(m_Character.Get_Current_YPos()
+ m_Character.GetYPos_Offset());
//m_Character_Jump.Update(GameTime);
}
if(m_Character.Get_Current_YPos() <= 200)
{
YPos_Flag = false;
}
if((m_Character.Get_Current_YPos() >= 400) && (m_Character.GetYPos_Offset() > 0))
{
Action_Flag = true;
YPos_Flag = true;
Drag_Offset = 0;
}
m_Character_Jump.setPosition(m_Character_Jump.Get_Current_XPos(),
m_Character_Jump.Get_Current_YPos());
m_Character_Jump.Update(GameTime);
break;
}
case 2:
{
m_Character.m_BoundBox.set(m_Character.GetX() + 50, m_Character.GetY() + 100,
m_Character.GetX() + 100, m_Character.GetY() + 300);
m_Character_Roll.Update(GameTime);
if(System.currentTimeMillis() - m_Timer >= 1500)
{
m_Timer = System.currentTimeMillis();
Action_Flag = true;
}
}
break;
}
}
m_Background[0].Update(GameTime);
m_Background[1].Update(GameTime, true);
if(System.currentTimeMillis() - m_Timer >= 3000)
{
if(m_Timer_Count > 4)
m_Timer_Count = 0;
else
m_Timer_Count++;
}
// for(int i = 0; i < m_Timer_Count; i++){
// if(m_Obstacle[i] != null)
// m_Obstacle[i].Update(GameTime);
// }
if(m_Obstacle[0] != null)
m_Obstacle[0].Update(GameTime);
if(m_Obstacle[1] != null)
m_Obstacle[1].Update(GameTime);
if(m_Obstacle[2] != null)
m_Obstacle[2].Update(GameTime);
// if(m_Obstacle[3] != null)
// m_Obstacle[3].Update(GameTime);
// if(m_Obstacle[4] != null)
// m_Obstacle[4].Update(GameTime);
// if(m_Obstacle[1].Get_M_X() < -400)
// m_Obstacle[1].SetCollisionFlag(true);
for(int i = 0; i < 3; i++){
m_Character_Life[i].Update(GameTime);
}
MakeObstacle();
CheckCollision();
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
public void CheckCollision()
{
for(int i = 0; i < 3; i++){
if(m_Obstacle[i] != null)
if(m_Obstacle[i].m_BoundFlag){
if(CollisionManager.CheckBoxToBox(m_Character.m_BoundBox, m_Obstacle[i].m_BoundBox)
||(CollisionManager.CheckBoxToBox(m_Character_Roll.m_BoundBox, m_Obstacle[i].m_BoundBox))){
//m_Character.destroyPlayer();
m_Obstacle[i].SetCollisionFlag(false);
AppManager.getInstance().GetGameView().VIBE();
if(m_Character.GetLife() <= 0)
{
AppManager.getInstance().GetGameView().ChangeGameState(new DeadState());
}
return ;
}
}
}
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
@Override
public void Render(Canvas canvas) {
// TODO 자동 생성된 메소드 스텁
m_Background[0].Draw(canvas);
m_Background[1].Draw(canvas);
// for(int i = 0; i < m_Timer_Count; i++){
if(m_Obstacle[0] != null)
m_Obstacle[0].Draw(canvas);
if(m_Obstacle[1] != null)
m_Obstacle[1].Draw(canvas);
if(m_Obstacle[2] != null)
m_Obstacle[2].Draw(canvas);
// if(m_Obstacle[3] != null)
// m_Obstacle[3].Draw(canvas);
// if(m_Obstacle[4] != null)
// m_Obstacle[4].Draw(canvas);
// }
for(int i = 0; i < 3; i++){
if(m_Character.GetLife() >= 3)
m_Character_Life[i].DrawLife(canvas);
else if(m_Character.GetLife() >= 2)
{
m_Character_Life[0].DrawLife(canvas);
m_Character_Life[1].DrawLife(canvas);
}
else if(m_Character.GetLife() >= 1)
m_Character_Life[0].DrawLife(canvas);
}
if(Action_Flag)
m_Character.Draw(canvas, true, m_HitCheck);
else if(!Action_Flag)
{
if(Drag_Offset == 1)
{
m_Character_Jump.Draw(canvas, false, m_HitCheck);
}
else if(Drag_Offset == 2)
{
m_Character_Roll.Draw(canvas, true, m_HitCheck);
}
}
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
public void MakeObstacle()
{
if(System.currentTimeMillis() - LastRegenObstacle >= 1000)
{
LastRegenObstacle = System.currentTimeMillis();
for(int i = 0; i <= 2; i++)//for(int i = 0; i <= m_Timer_Count; i++)
{
Temp_XPos = 0;
Temp_YPos = 0;
switch(i)
{
case 0:
{
if(m_Obstacle[i] == null)
m_Obstacle[i] = new Obstacle_1();
m_Obstacle[i].SetCollisionFlag(true);
m_Obst_Number = i;
SetObstacleXPos(200, false);
SetObstacleXPos(((int) Math.random() *1400) + 1500, true);
SetObstacleYPos(m_Obstacle[i].Get_Random_Obstacle_YPos());
Log.v("m_x", "m_x : " + m_Obstacle[i].Get_M_X());
if(m_Obstacle[i].Get_M_X() < -400)
m_Obstacle[i].setPosition(Temp_XPos, Temp_YPos);
Log.v("m_x", "Setposition m_x : " + m_Obstacle[0].Get_M_X());
}
break;
case 1:
{
Log.v("Count Check", "true");
if(m_Obstacle[i] == null)
m_Obstacle[i] = new Obstacle_2();
m_Obstacle[i].SetCollisionFlag(true);
m_Obst_Number = i;
SetObstacleXPos(400, false);
SetObstacleXPos(((int) Math.random() *1800) + 1900, true);
SetObstacleYPos(m_Obstacle[i].Get_Random_Obstacle_YPos());
if(m_Obstacle[i].Get_M_X() < -400)
m_Obstacle[i].setPosition(Temp_XPos, Temp_YPos);
}
break;
case 2:
{
if(m_Obstacle[2] == null)
m_Obstacle[2] = new Obstacle_3();
m_Obstacle[i].SetCollisionFlag(true);
m_Obst_Number = 2;
SetObstacleXPos(400, false);
SetObstacleXPos(((int) Math.random() *2000) + 2100, true);
SetObstacleYPos(m_Obstacle[2].Get_Random_Obstacle_YPos());
if(m_Obstacle[2].Get_M_X() < -400)
m_Obstacle[2].setPosition(Temp_XPos, Temp_YPos);
}
break;
case 3:
{
if(m_Obstacle[3] == null)
m_Obstacle[3] = new Obstacle_4();
m_Obstacle[i].SetCollisionFlag(true);
m_Obst_Number = 3;
SetObstacleXPos(400, false);
SetObstacleXPos(((int) Math.random() *2300) + 2400, true);
SetObstacleYPos(m_Obstacle[3].Get_Random_Obstacle_YPos());
if(m_Obstacle[3].Get_M_X() < -400)
m_Obstacle[3].setPosition(Temp_XPos, Temp_YPos);
}
break;
case 4:
{
if(m_Obstacle[4] == null)
m_Obstacle[4] = new Obstacle_5();
m_Obstacle[i].SetCollisionFlag(true);
m_Obst_Number = 4;
SetObstacleXPos(400, false);
SetObstacleXPos(((int) Math.random() *2500) + 2600, true);
SetObstacleYPos(m_Obstacle[4].Get_Random_Obstacle_YPos());
if(m_Obstacle[4].Get_M_X() < -400)
m_Obstacle[4].setPosition(Temp_XPos, Temp_YPos);
}
break;
}
}
}
}
public void SetObstacleXPos(int XPos, boolean AddFlag)
{
if(!AddFlag)
Temp_XPos = XPos;
else
Temp_XPos += XPos;
}
public void SetObstacleYPos(int YPos)
{
Temp_YPos = YPos;
}
public int GetObstacleXPos()
{
return Temp_XPos;
}
public int GetObstacleYPos()
{
return Temp_YPos;
}
public int GetrandObst()
{
return m_Obst_Number;
}
public int GetTempXPos()
{
return Temp_XPos;
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO 자동 생성된 메소드 스텁
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int m_x = (int) (event.getX());
int m_y = (int) (event.getY());
if (event.getAction() == MotionEvent.ACTION_DOWN) {
Log.v("MoveLog", "true!");
if(Action_Flag == true)
{
Log.v("MoveLog", "true~!");
Drag_Start_Position = event.getY();
}
return true;
}
if(event.getAction() == MotionEvent.ACTION_MOVE) {
if(Action_Flag == true)
{
Drag_End_Position = event.getY();
}
return true;
}
if(event.getAction() == MotionEvent.ACTION_UP){
if(Action_Flag == true)
{
if(Drag_Start_Position > Drag_End_Position + 100)
{
Drag_Start_Position = 0.0f;
Drag_End_Position = 0.0f;
Drag_Offset = 1;
Action_Flag = false;
}
else if(Drag_Start_Position + 100 < Drag_End_Position)
{
Drag_Start_Position = 0.0f;
Drag_End_Position = 0.0f;
Drag_Offset = 2;
Action_Flag = false;
}
return true;
}
}
return false;
}
}