Python Forum
index error when using lists to blit rotated images
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
index error when using lists to blit rotated images
#1
Hello, I am getting an index error when trying to use lists of rotated images. originally, to rotate images of 2 spaceships (think asteroids), I used a function to rotozoom each image for every degree change. It worked, but not surprisingly, it was lagging. I read that "cached images" might be a better choice, so I have preloaded two lists with 72 images each (5 degree increments through 360 degrees). However, after making one full rotation either cw or ccw, I get: in ship_draw
win.blit(self.image_list[self.rot_angle_index], (self.x_move - int(self.image_list[self.rot_angle_index].get_width() / 2), self.y_move - int(
IndexError: list index out of range

Even though I am ensuring the index value returns to 0, it won't display the image. Any help would be appreciated as to why this is happening and how to fix it. Thanks!

class spaceship(object):
    def __init__(self, x_move, y_move, width, height, rot, image):
        self.x_move = x_move
        self.y_move = y_move
        self.width = width
        self.height = height
        self.rot_angle = rot
        self.vel = 0
        self.hspeed = 0
        self.vspeed = 0
        self.thrust = False
        self.rotated = False
        self.fired_shots_delay = 10
        self.image = image
        self.image_list = []
        self.rot_angle_index = 0
        self.shield = 100
        self.visable = True
        self.score = 0

        self.image_list.append(self.image)
        for i in range(1, 71):
            holder = pygame.transform.rotozoom(self.image, i * 5, 1)
            self.image_list.append(holder)


    def ship_draw(self, win, list, angle):
        
        if self.rot_angle <= -360 or self.rot_angle >= 360:
            self.rot_angle = self.rot_angle - (360 * (ship_one.rot_angle // 360))

        self.rot_angle_index = self.rot_angle // 5

        if self.visable:

            win.blit(self.image_list[self.rot_angle_index], (self.x_move - int(self.image_list[self.rot_angle_index].get_width() / 2), 
                 self.y_move - int(self.image_list[self.rot_angle_index].get_height() / 2)))
        else:
            self.reset()
            win.blit(self.image_list[self.rot_angle_index],
                     (self.x_move - int(self.image_list[self.rot_angle_index].get_width() / 2), self.y_move - int(
                         self.image_list[self.rot_angle_index].get_height() / 2)))

        #  screen wrap
        if self.x_move > game_screen_x:
            self.x_move = 0
        elif self.x_move < 0:
            self.x_move = game_screen_x
        elif self.y_move > game_screen_y:
            self.y_move = 40
        elif self.y_move < 40:
            self.y_move = game_screen_y


# These are called right before main game loop

ship_one = spaceship(left_rnd_location_x, left_rnd_location_y, 32, 32, 0, ship_one_image)
ship_two = spaceship(right_rnd_location_x, right_rnd_location_y, 32, 32, 0, ship_two_image)

# Called at end of game loop before pygame.display.flip

ship_one.ship_draw(win, ship_one.image_list, ship_one.rot_angle)
ship_two.ship_draw(win, ship_two.image_list, ship_two.rot_angle)
Reply
#2
We can't see in the error message which line is giving the problem.
So my guess is that Line 22 counts 70 ticks:
and at first sight this is 2 shy from the 72 images you are talking about.
Paul
It is more important to do the right thing, than to do the thing right.(P.Drucker)
Better is the enemy of good. (Montesquieu) = French version for 'kiss'.
Reply
#3
(Sep-01-2020, 06:52 AM)DPaul Wrote: and at first sight this is 2 shy from the 72 images you are talking about.
actually they have one image already in the list, so total of 71 images, still not 72 as OP expects

As to design - it may be better to use dict with angle as key, instead of converting the angle to index in list
For debug - I would print both angle and index just before the problem line
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#4
Thanks to you both for your replies. I was playing around with the suggestions and realized my mistake...I forgot to change ship_one.rot_angle to self.rot_angle. It works now. If possible, buran, would you elaborate on the using dict with angle as key, instead of my conversion to an index? I am new to python and coding...
Reply
#5
(Sep-02-2020, 11:44 PM)codefun45 Wrote: I forgot to change ship_one.rot_angle to self.rot_angle. It works now.
can you post your current code for the class, because there are number of issues in your Spaceship.ship_draw() method:
  • it takes arguments, that are in fact available as properties of the class and should be used instead - list, angle. This and other similar mistakes make me think you don't understand the concept of class.
  • using self.reset() on line#39 - there is no Spaceship.reset() method
  • not sure where get_height() and get_width() methods you apply on the image come from (we don't know what object is ship_one_image, so they may be available for whatever object it is)

There are also other problems with your class, but let's start with these
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#6
Here is what I have so far.

import pygame
import math
import random

pygame.init()
pygame.font.init()

clock = pygame.time.Clock()

infoObject = pygame.display.Info()

game_screen_x = infoObject.current_w - 50
game_screen_y = infoObject.current_h - 100

win = pygame.display.set_mode((game_screen_x, game_screen_y))

screen_center_x = int(game_screen_x / 2)
screen_center_y = int(game_screen_y / 2)

left_rand_location_x = 0
left_rand_location_y = 0
right_rand_location_x = 0
right_rand_location_y = 0

pygame.display.set_caption("SpaceDemoDerby")

# define colors
black = (0, 0, 0)
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)
lightblue = (173, 216, 230)
grey = (87, 87, 87)
offwhite = (230, 230, 230)

# load images
back_ground = pygame.image.load('bg.png').convert()
pygame.transform.scale(back_ground, (game_screen_x, game_screen_y))

load_image_one = pygame.image.load('blueship.png').convert_alpha()
load_image_two = pygame.image.load('redship.png').convert_alpha()
load_image_one.set_colorkey(black)
load_image_two.set_colorkey(black)
ship_one_image = pygame.transform.scale(load_image_one, (32, 32))
ship_two_image = pygame.transform.scale(load_image_two, (32, 32))

explosion_anim = {}
explosion_anim['boom'] = []
for i in range(6):
    filename = 'exp{}.png'.format(i)
    img = pygame.image.load(filename).convert()
    img.set_colorkey(black)
    explosion_anim['boom'].append(img)

# load music and sound effects
music = pygame.mixer.music.load('unbreakable havoc redone.wav')
pygame.mixer.music.play(-1)

shoot_sound = pygame.mixer.Sound('Laser.wav')
explode_sound = pygame.mixer.Sound('Explosion.wav')
shield_sounds = []
for i in range(5):
    filename = 'Metal_sounds_{}.wav'.format(i)
    snd = pygame.mixer.Sound(filename)
    shield_sounds.append(snd)
crash_sounds = []
for i in range(4):
    filename = 'crash{}.wav'.format(i)
    snd = pygame.mixer.Sound(filename)
    crash_sounds.append(snd)

#  starter variables
bullet_speed = 15
fd_fric = 0.5
bd_fric = 0.1
player_max_speed = 10
rotation_max_speed = 5

all_sprites = pygame.sprite.Group()

left_rnd_location_x = random.randint(25, (screen_center_x - 50))
left_rnd_location_y = random.randint(25, (screen_center_y - 50))
right_rnd_location_x = random.randint((screen_center_x + 50), (game_screen_x - 25))
right_rnd_location_y = random.randint((screen_center_y - 50), (game_screen_y - 25))

#  fonts
font1 = pygame.font.SysFont('Arial', 20, True)
font2 = pygame.font.SysFont('Arial', 16)
font3 = pygame.font.SysFont('Arial', 28, True, True)

class explosion(pygame.sprite.Sprite):
    def __init__(self, center, name):
        pygame.sprite.Sprite.__init__(self)
        self.name = name
        self.image = explosion_anim[self.name][0]
        self.rect = self.image.get_rect()
        self.rect.center = center
        self.frame = 0
        self.last_update = pygame.time.get_ticks()
        self.frame_rate = 60

    def update(self):
        now = pygame.time.get_ticks()
        if now - self.last_update > self.frame_rate:
            self.last_update = now
            self.frame += 1
            if self.frame == len(explosion_anim[self.name]):
                self.kill()
            else:
                center = self.rect.center
                self.image = explosion_anim[self.name][self.frame]
                self.rect = self.image.get_rect()
                self.rect.center = center


class bullet(object):
    def __init__(self, x, y, dir, color):
        self.x = x
        self.y = y
        self.dir = dir
        self.color = color
        self.life = 60

    def updatebullet(self):
        self.x += bullet_speed * math.cos((self.dir + 90) * math.pi / 180)
        self.y += bullet_speed * -math.sin((self.dir + 90) * math.pi / 180)

        pygame.draw.circle(win, self.color, (int(self.x), int(self.y)), 3)

        self.life -= 1


class spaceship(object):
    def __init__(self, x_move, y_move, width, height, rot, image):
        self.x_move = x_move
        self.y_move = y_move
        self.width = width
        self.height = height
        self.rot_angle = rot
        self.vel = 0
        self.hspeed = 0
        self.vspeed = 0
        self.thrust = False
        self.rotated = False
        self.fired_shots_delay = 10
        self.image = image
        self.image_list = []
        self.rot_angle_index = 0
        self.shield = 100
        self.visable = True
        self.score = 0

        for i in range(72):
            holder = pygame.transform.rotozoom(self.image, i * 5, 1)
            self.image_list.append(holder)

    def propulsion(self):  # from asteroids
        speed = math.sqrt(self.hspeed ** 2 + self.vspeed ** 2)
        if self.thrust:
            if speed + fd_fric < player_max_speed:
                self.hspeed += fd_fric * math.cos((self.rot_angle + 90) * math.pi / 180)
                self.vspeed += fd_fric * -math.sin((self.rot_angle + 90) * math.pi / 180)
            else:
                self.hspeed = player_max_speed * math.cos((self.rot_angle + 90) * math.pi / 180)
                self.vspeed = player_max_speed * -math.sin((self.rot_angle + 90) * math.pi / 180)
        else:
            if speed - bd_fric > 0:
                change_in_hspeed = (bd_fric * math.cos(self.vspeed / self.hspeed))
                change_in_vspeed = (bd_fric * math.sin(self.vspeed / self.hspeed))
                if self.hspeed != 0:
                    if change_in_hspeed / abs(change_in_hspeed) == self.hspeed / abs(self.hspeed):
                        self.hspeed -= change_in_hspeed
                    else:
                        self.hspeed += change_in_hspeed
                if self.vspeed != 0:
                    if change_in_vspeed / abs(change_in_vspeed) == self.vspeed / abs(self.vspeed):
                        self.vspeed -= change_in_vspeed
                    else:
                        self.vspeed += change_in_vspeed
            else:
                self.hspeed = 0
                self.vspeed = 0
        self.x_move += self.hspeed
        self.y_move += self.vspeed

    def ship_draw(self, win, list, angle):

        if self.rot_angle <= -360 or self.rot_angle >= 360:
            self.rot_angle = self.rot_angle - (360 * (self.rot_angle // 360))

        self.rot_angle_index = self.rot_angle // 5

        if self.visable:

            win.blit(self.image_list[self.rot_angle_index], (self.x_move - int(self.image_list[self.rot_angle_index].get_width() / 2), self.y_move - int(
                    self.image_list[self.rot_angle_index].get_height() / 2)))
            print (self.rot_angle, self.rot_angle_index)
        else:

            self.reset()
            win.blit(self.image_list[self.rot_angle_index],
                     (self.x_move - int(self.image_list[self.rot_angle_index].get_width() / 2), self.y_move - int(
                         self.image_list[self.rot_angle_index].get_height() / 2)))



        #  screen wrap
        if self.x_move > game_screen_x:
            self.x_move = 0
        elif self.x_move < 0:
            self.x_move = game_screen_x
        elif self.y_move > game_screen_y:
            self.y_move = 40
        elif self.y_move < 40:
            self.y_move = game_screen_y


    def hitship(self):
        if self.shield > 0:
            self.shield -= 10
            if self.shield < 0:
                self.shield = 0
        random.choice(shield_sounds).play()

    def reset(self):
        if not ship_one.visable:
            self.x_move = random.randint(25, (screen_center_x - 50))
            self.y_move = random.randint(50, (game_screen_y - 25))

        if not ship_two.visable:
            self.x_move = random.randint((screen_center_x + 50), (game_screen_x - 25))
            self.y_move = random.randint(50, (game_screen_y - 25))

        self.rot_angle = 0
        self.hspeed = 0
        self.vspeed = 0
        self.thrust = False
        self.rotated = False
        self.visable = True

        ship_one.shield = 100
        ship_two.shield = 100


def shipscollide(rect_one, rect_two):
    c_tolerance = 10
    ship_one.thrust = False
    ship_two.thrust = False
    if abs(rect_two.top - rect_one.bottom) < c_tolerance:
        if ship_one.hspeed > 0 or ship_two.hspeed < 0:
            ship_one.vspeed *= -1
            ship_two.vspeed *= -1
    if abs(rect_two.bottom - rect_one.top) < c_tolerance:
        if ship_one.hspeed < 0 or ship_two.hspeed > 0:
            ship_one.vspeed *= -1
            ship_two.vspeed *= -1
    if abs(rect_two.right - rect_one.left) < c_tolerance:
        if ship_one.hspeed < 0 or ship_two.hspeed > 0:
            ship_one.hspeed *= -1
            ship_two.hspeed *= -1
    if abs(rect_two.left - rect_one.right) < c_tolerance:
        if ship_one.hspeed > 0 or ship_two.hspeed < 0:
            ship_one.hspeed *= -1
            ship_two.hspeed *= -1

    if abs(rect_two.top - rect_one.left) < c_tolerance:
        if ship_one.hspeed > 0 or ship_two.hspeed < 0:
            ship_one.vspeed *= -1
            ship_two.vspeed *= -1
    if abs(rect_two.bottom - rect_one.right) < c_tolerance:
        if ship_one.hspeed < 0 or ship_two.hspeed > 0:
            ship_one.vspeed *= -1
            ship_two.vspeed *= -1
    if abs(rect_two.right - rect_one.top) < c_tolerance:
        if ship_one.hspeed < 0 or ship_two.hspeed > 0:
            ship_one.hspeed *= -1
            ship_two.hspeed *= -1
    if abs(rect_two.left - rect_one.bottom) < c_tolerance:
        if ship_one.hspeed > 0 or ship_two.hspeed < 0:
            ship_one.hspeed *= -1
            ship_two.hspeed *= -1

    if abs(rect_two.top - rect_one.top) < c_tolerance:
        if ship_one.hspeed > 0 or ship_two.hspeed < 0:
            ship_one.vspeed *= -1
            ship_two.vspeed *= -1
    if abs(rect_two.bottom - rect_one.bottom) < c_tolerance:
        if ship_one.hspeed < 0 or ship_two.hspeed > 0:
            ship_one.vspeed *= -1
            ship_two.vspeed *= -1
    if abs(rect_two.right - rect_one.right) < c_tolerance:
        if ship_one.hspeed < 0 or ship_two.hspeed > 0:
            ship_one.hspeed *= -1
            ship_two.hspeed *= -1
    if abs(rect_two.left - rect_one.left) < c_tolerance:
        if ship_one.hspeed > 0 or ship_two.hspeed < 0:
            ship_one.hspeed *= -1
            ship_two.hspeed *= -1

    if abs(rect_two.bottom - rect_one.left) < c_tolerance:
        if ship_one.hspeed > 0 or ship_two.hspeed < 0:
            ship_one.vspeed *= -1
            ship_two.vspeed *= -1
    if abs(rect_two.top - rect_one.right) < c_tolerance:
        if ship_one.hspeed < 0 or ship_two.hspeed > 0:
            ship_one.vspeed *= -1
            ship_two.vspeed *= -1
    if abs(rect_two.right - rect_one.bottom) < c_tolerance:
        if ship_one.hspeed < 0 or ship_two.hspeed > 0:
            ship_one.hspeed *= -1
            ship_two.hspeed *= -1
    if abs(rect_two.left - rect_one.top) < c_tolerance:
        if ship_one.hspeed > 0 or ship_two.hspeed < 0:
            ship_one.hspeed *= -1
            ship_two.hspeed *= -1

    impact_damage = [2, 5, 10]

    if ship_one.shield > 0:
        ship_one.shield -= random.choice(impact_damage)
        if ship_one.shield < 0:
            ship_one.shield = 0
    if ship_two.shield > 0:
        ship_two.shield -= random.choice(impact_damage)
        if ship_two.shield < 0:
            ship_two.shield = 0

    random.choice(crash_sounds).play()


def collision(bx, by, sx, sy, size):
    if bx > sx - size and bx < sx + size and by > sy - size and by < sy + size:
        return True
    return False


def status_bar():
    # background bar
    pygame.draw.rect(win, grey, (0, 0, game_screen_x, 45))

    #Title
    title_text = font3.render('SPACE DEMO DERBY', True, black)
    win.blit(title_text, (800, 10))

    # score
    score1_text = font1.render('Red Ships Destroyed: ' + str(ship_one.score), True, offwhite)
    score2_text = font1.render('Blue Ships Destroyed: ' + str(ship_two.score), True, offwhite)
    win.blit(score1_text, (410, 10))
    win.blit(score2_text, (game_screen_x - 648, 10))

    # shield health bars
    shield1_text = font2.render('SHIELD INTEGRITY', True, offwhite)
    win.blit(shield1_text, (245, 15))
    win.blit(shield1_text, (game_screen_x - 395, 15))

    pygame.draw.rect(win, red, (40, 15, 200, 15))
    pygame.draw.rect(win, red, (game_screen_x - 240, 15, 200, 15))
    pygame.draw.rect(win, green, (40, 15, 200 - (2 * (100 - ship_one.shield)), 15))
    pygame.draw.rect(win, green, (game_screen_x - 240, 15, 200 - (2 * (100 - ship_two.shield)), 15))

def clear_screen():
    win.fill((0, 0, 0))
    win.blit(back_ground, (0, 0))


# create a spaceship

ship_one = spaceship(left_rnd_location_x, left_rnd_location_y, 32, 32, 0, ship_one_image)
ship_two = spaceship(right_rnd_location_x, right_rnd_location_y, 32, 32, 0, ship_two_image)

# initial variables
s1_fired_shots = []
s2_fired_shots = []
fired_shots_cap = 10
shot_delay_constant = 10
run = True

# main loop
while run:
    clock.tick(80)

    for shot in s1_fired_shots:
        if shot.life == 0:
            s1_fired_shots.pop(s1_fired_shots.index(shot))
    for shot in s2_fired_shots:
        if shot.life == 0:
            s2_fired_shots.pop(s2_fired_shots.index(shot))

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_e:
                ship_one.thrust = True
            if event.key == pygame.K_KP8:
                ship_two.thrust = True

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_e:
                ship_one.thrust = False
            if event.key == pygame.K_KP8:
                ship_two.thrust = False

    keys = pygame.key.get_pressed()

    if keys[pygame.K_f]:  # CW rotation
        ship_one.rot_angle -= rotation_max_speed
    if keys[pygame.K_KP6]:
        ship_two.rot_angle -= rotation_max_speed
    if keys[pygame.K_s]:   #CCW rotation
        ship_one.rot_angle += rotation_max_speed
    if keys[pygame.K_KP4]:
        ship_two.rot_angle += rotation_max_speed

    if keys[pygame.K_TAB] and len(s1_fired_shots) < fired_shots_cap:
        if ship_one.fired_shots_delay == 0:
            s1_fired_shots.append(bullet(ship_one.x_move, ship_one.y_move, ship_one.rot_angle, lightblue))
            # shoot_sound.play()
            ship_one.fired_shots_delay = shot_delay_constant
        else:
            ship_one.fired_shots_delay -= 1

    if keys[pygame.K_RETURN] and len(s2_fired_shots) < fired_shots_cap:
        if ship_two.fired_shots_delay == 0:
            s2_fired_shots.append(bullet(ship_two.x_move, ship_two.y_move, ship_two.rot_angle, red))
            # shoot_sound.play()
            ship_two.fired_shots_delay = shot_delay_constant
        else:
            ship_two.fired_shots_delay -= 1


    clear_screen()

    #  movement
    ship_one.propulsion()
    ship_two.propulsion()


    all_sprites.update()

    #  check for bullet hits

    for shot in s1_fired_shots:
        shot.updatebullet()

        if ship_two.visable:
            if collision(shot.x, shot.y, ship_two.x_move, ship_two.y_move, 32):
                ship_two.hitship()
                s1_fired_shots.pop(s1_fired_shots.index(shot))
                if ship_two.shield <= 0:
                    tmp = pygame.Rect(ship_two.x_move, ship_two.y_move, 32, 32)
                    exp = explosion(tmp.topleft, 'boom')
                    explode_sound.play()
                    all_sprites.add(exp)
                    ship_two.visable = False
                    ship_one.score += 1


    for shot in s2_fired_shots:
        shot.updatebullet()

        if ship_one.visable:
            if collision(shot.x, shot.y, ship_one.x_move, ship_one.y_move, 32):
                ship_one.hitship()
                s2_fired_shots.pop(s2_fired_shots.index(shot))
                if ship_one.shield <= 0:
                    tmp = pygame.Rect(ship_one.x_move, ship_one.y_move, 32, 32)
                    exp = explosion(tmp.topleft, 'boom')
                    explode_sound.play()
                    all_sprites.add(exp)
                    ship_one.visable = False
                    ship_two.score += 1


    # check for ship collisions
    if ship_one.visable and ship_two.visable:
        tmp1 = pygame.Rect(ship_one.x_move, ship_one.y_move, 32, 32)
        tmp2 = pygame.Rect(ship_two.x_move, ship_two.y_move, 32, 32)
        # if collision(ship_one.x_move, ship_one.y_move,ship_two.x_move, ship_two.y_move, 24):
        # shipscollide(tmp1, tmp2)
        if tmp1.colliderect(tmp2):
            shipscollide(tmp1, tmp2)
            if ship_two.shield <= 0:
                tmp = pygame.Rect(ship_two.x_move, ship_two.y_move, 32, 32)
                exp = explosion(tmp.topleft, 'boom')
                explode_sound.play()
                all_sprites.add(exp)
                ship_two.visable = False
                ship_one.score += 1

            if ship_one.shield <= 0:
                tmp = pygame.Rect(ship_one.x_move, ship_one.y_move, 32, 32)
                exp = explosion(tmp.topleft, 'boom')
                explode_sound.play()
                all_sprites.add(exp)
                ship_one.visable = False
                ship_two.score += 1

    #  draw new positions


    ship_one.ship_draw(win, ship_one.image_list, ship_one.rot_angle)
    ship_two.ship_draw(win, ship_two.image_list, ship_two.rot_angle)

    status_bar()

    all_sprites.draw(win)

    pygame.display.flip()

pygame.quit()
Reply
#7
I moved this to game development, because I think people who are more familiar with pygame can give you better advise/feedback on your code. My idea was to use a dict with angle, e.g. 0, 5, 10, 15... 355 to hold images and then use directly self.rot_angle to get respective image, instead of converting rot_angle to index and retrieving image from list. However I think you have much serious problems with your code and this change is minor compared to them.
for example, in your spaceship.ship_draw() method you have list parameter. as already mentioned - this is bad name, but more importantly - you already have self.images_list and you work with it. There is no need to pass it as argument when you call the method. Same for rot_angle. width and height - are these width and height of the image? why pass them when instantiate the class? and so on...
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#8
I appreciate the input, and your time, buran. Thanks, again.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  [PyGame] pygame blit() method syafiq14 1 4,832 Oct-30-2020, 04:46 PM
Last Post: Russ_CW
  [PyGame] I found a way to generate sprites without .blit. Is it effecient? xBlackHeartx 19 8,228 Dec-07-2019, 01:06 PM
Last Post: metulburr
  moving image with blit rwahdan 2 2,978 Jul-10-2019, 06:24 PM
Last Post: nilamo
  error with survace.blit joemcsk1 3 4,390 Aug-06-2018, 12:23 AM
Last Post: metulburr
  Raspberry Pi pygameui - Fails with error index out of range erhixon 0 2,882 Sep-19-2017, 01:36 PM
Last Post: erhixon

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020