우리가 객체지향에서 객체를 누가 생성하는지에 대한 생성에 관한 것이 중요하고, 때론 특히나 게임개발에서는 소멸시점에 대해서도 함께 고려할 필요가 있는데 총알객체라고 하는 부분이 이에 해당할 수 있다. 총알객체는 탱크(주인공 탱크, 적 탱크)가 생성하는 것은 당연한데 주인공 탱크는 게임유저의 조작, 즉, 스페이스바를 누를 때 생성되야 하고, 적 탱크는 컴퓨터에 의해 자동으로 랜덤발사가 된다. 그밖에 총알의 소멸시점은 총 3가지로 고려될 수 있는데, 먼저, 총알이 날아가다가 벽과 충돌할 때, 상대 탱크와 충돌할 때, 마지막으로 중간에 아무 충돌없이 화면 밖으로 나갔을 때이다.
먼저, 기존 총알 객체에는 총알 날아가는 것에 대한 구현이 빠져있는데, move 라는 메소드를 추가하되, 총알이 동서남북 어디로 날지는 angle 속성값으로 결정되게 된다. 탱크 객체는 객체 이용자에게 총알을 쏘는 서비스를 제공해야 하고, 이를 fire 라는 메소드를 만들어 제공하기로 한다. 그리고, 총알 객체가 만들어지는 시점도 바로 이 함수가 호출되는 시점이라 할 수 있다.
🔢 35라인에서 총알객체를 생성하면서 총알객체의 첫 위치는 탱크 그 자신의 중심점에 존재행야 하기 때문에 self.pos 라는 좌표값를 인자값로 넘겼다는 것을 기억하자. 그리고, 화면경계에 대한 튜플값 (self.s_width, self.s_height) 은 28라인의 CheckOutOfScreen 부모객체의 초기화 때 이미 설정해놨기 때문에 부모에 존재하는 그 속성값을 자식은 마치 본인의 속성값처럼 사용할 수 있는 것이다.
🔢battle_city_oop.py 코드 내 update 함수에서 주인공 탱크의 총알 재장전 속도를 지연시키기 위한 코드 부분은 절차지향 때의 알고리즘하고 동일하여 이해에 큰 어려움은 없을 것이다. 절차지향에서는 총알발사 소리에 대한 재생을 직접했다면, 객체지향에서는 소리재생 부분도 객체에게 위임하고 있다.
지금까지 코딩된 부분을 실행시켜보면, 적 탱크들이 자동으로 총알발사가 일어나고, 주인공 탱크도 스페이스바가 눌려진 시점에 발포소리와 함께 총알생성이 잘 이뤄질 것이다. 다만, 생성된 총알이 실제 움직여 날아가지 않을 텐데, 그 이유는 우리가 아직 실제 총알 움직임을 만들고 충돌검사를 하는 부분의 코드를 추가하지 않았기 때문이고, 이제 그 부분의 코드를 함께 추가해 보도록 하자.
actors.py
classTank(Actor,CheckOutOfScreen): ... 생략defcollidelist_bullets(self,tanks):battle_city_oop.py tank_index =-1for bullet in self.bullets: bullet.move()# 화면경계 확인if bullet.is_out_of_screen(): self.bullets.remove(bullet)# 벽 더미 확인 wall_index = bullet.collidelist(self.walls)if wall_index !=-1:del self.walls[wall_index] self.bullets.remove(bullet)# 상대 탱크 확인 tank_index = bullet.collidelist(tanks)if tank_index !=-1: self.bullets.remove(bullet)return tank_index
battle_city_oop.py
defupdate():global enemy_move_cnt, bullet_delay_cnt# 주인공 탱크 ... 생략 enemy_idx = tank.collidelist_bullets(enemies)if enemy_idx !=-1:del enemies[enemy_idx]iflen(enemies)==0: winner ="You"# 적 탱크for enemy in enemies: ... 생략 tank_idx = enemy.collidelist_bullets([tank])if tank_idx !=-1: winner ="Enemy"
🔢 우리는 탱크 부모 객체에 collidelist_bullets 라는 멤버함수를 구현했다. 이 함수의 역할은 총알이 있을 경우, 총알의 움직임을 만들고(8번 라인), 그 총알이 날아가다가 벽 더미, 또는 상대 탱크와 충돌이 생기거나 충돌없이 화면 밖을 나가면 총알객체를 제거한다.(12, 18, 23라인). 그리고, 리턴값으로는 탱크에 총알이 명중했냐의 유무가 중요하기 때문에 그에 따른 결과를 리턴한다.
반면에 battle_city_oop.py 안 update 함수 안에서는 이 멤버함수를 반복적으로 호출하므로써 멤버함수의 리턴값을 통해 총알의 명중유무를 판별 후 예를 들어, 적 탱크가 명중하면 명중된 탱크를 제거 하는 등(9번 라인) 이 결과를 게임에 반영하는 코드가 추가되었다. 여기서 winner 라는 변수는 절차지향형 버전에서도 사용했던 동일한 내용으로 게임의 승자판별을 목적하는 값으로 winner 라는 변수에 담긴 값에 따라 추후 화면중앙에서 게임결과가 큰 텍스트 형태로 표시된다.
드디어, 우리 게임의 거의 대부분을 완성했고 마지막 남은 부분은 명중된 탱크의 폭발장면의 에니메이션을 추가하는 부분이 남아있다. 남은 부분은 최종 완성은 다음 절로 넘겨 진행하도록 하겠다.