Author Archives: Rohin Knight

Custom Maps for Call of Duty United Offensive

I often play LAN games with my friends. One game we often play is Call of Duty United Offensive. Although this game is a bit old now, the multi-player part never gets boring.

After we had tried out every map we could find, I decided to try creating my own. It was a little tricky getting started, but once I got the hang of it I found map building to be quite addictive.

Here are most of the maps I created. There is a link at the bottom to download them all.

Garden Tower (2 to 4 players)

shot0010 shot0025
shot0027 shot0024shot0026

Garden Tower was the first map I created. You have a tower with grenades and bazookas at the top. There are two ways to get up, with a spiral staircase on the inside and a ladder on the outside.

There are plenty of trees and bushes which provide for good cover, and  two mounted machine guns, with one able to shoot anyone at the top of the tower. There is also a tree you can hide in and sniper from.

At the top of the tower you can look out over the wall.

4 Walls and a Tree (2 to 3 players)

shot0040 shot0037

This is a cut down version of garden tower, and as the name suggests it just consists of 4 walls with a tree in the middle. 3 of the walls have holes in them for sniping from, and there is a platform in the tree for hiding and sniping from as well. Perfect for just 2 players.

Warehouse (5 – 10 players)

cod_map_editing_v2 cod_map_editing_v1 shot0022 shot0020  shot0018 shot0016 shot0015 shot0023 

This map definitely took the longest to build, and I ended up making it too big. As you can see from the screenshots, the map is quite dark in most places, so plenty of places to hide.

There are stacks of boxes on the floor, with several catwalks overhead at different heights. You can reach different levels by climbing ladders or through protected passageways connecting to 3 stairwells in different corners. There is also a sewers at the bottom.

Jeep Race (2 – 7 players)

shot0036 shot0035

One thing I thought would be fun was to design a racing course for jeeps. It also provided a great way to test the game’s physics with vehicles (turns out to be not that great).

The racing course consists of different slopes with mines and jumps. You can either race your friend in another jeep, or try and shoot them from the side.

Skyfall (3 – 5 players)

shot0042 shot0043

My friend came up with the idea for this map. There are several towers linked together and the mist is so think you can only ever see as far as the next tower.

Hide and Seek (2 – 5 players)

shot0009

As the name suggests this map is all about hide and seek. Some dark areas need to be avoided though unless you want to fall into a pit

The Pit (2 – 5 players)

shot0047

You have a 1 in 3 chance of spawning in the pit, which is not a good place to be.

Download

You can download the first 6 maps here: http://snk.to/f-chjlv0am – and the 7th map can be downloaded here: http://snk.to/f-chkiykk7 (Place .pk3 files in the uo sub-folder for Call of Duty)

And the map source files can be downloaded here: http://snk.to/f-c7xplxxg

Please let me know if any links are broken.

Advertisements

How to fix headphone jack and cam in Ubuntu on Asus A52J

After I had installed Ubuntu 10.10 on my Asus A52J laptop, I had two issues
1. The sound wouldn’t play through headphones when I plugged them in.
2. May webcam was upside down in Skype.

I found the answers in these two forum posts:
http://ubuntuforums.org/showthread.php?t=1612004
http://ubuntuforums.org/showthread.php?t=1460790&page=12

Headphones problem
1. Create file /etc/modprobe.d/sound.conf, and enter the following:

options snd-hda-intel model=ideapad

2. Reboot (or reload snd-hda-intel)

Skype cam problem
To fix the cam in Skype, create a bash script in your home directory

#!/bin/bash
export LIBV4LCONTROL_FLAGS=3 && LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so skype

iPhone Development in Ubuntu Linux

Here is what I did to setup Snow Leopard with xcode in Virtualbox and deploy my work to my iPhone.

I’m running Ubuntu Linux on my Asus A52J laptop with an Intel i3 CPU and 2 GB of RAM

UPDATE: Virtualbox 4 keeps aborting when I add my iPod to snow leopard. I’ve reverted back to using version 3.2.12. Please let me know if you get it working in version 4.

Install Snow Leopard
www.sysprobs.com has many useful tutorials for installing Snow Leopard in Virtualbox. I used this one for installing it on my Intel i3: http://www.sysprobs.com/mac-os-snow-leopard-intel-i3i5-i7-processors-virtualbox

You will need a copy of snow leopard. I first downloaded a copy of Snow Leopard and then purchased a copy after I had confirmed everything was working. If you decide to do this then please don’t be a pirate by not purchasing a copy after you have everything working. You can probably pick up a secondhand copy of Snow Leopard somewhere for a good price.

You will also need eboot.iso because Virtualbox will not be able to boot directly into Snow Leopard.

Next, download Virtualbox and create a machine with the following setup:

  • Set OS to Mac OSX and version to Mac OSX Server
  • Create a dynamically expanding hard disk of with a size of 25GB or more. Snow leopard and xcode will take up almost 20GB combined. Set memory to 1024MB (or more if possible). I first tried to install OSX under Windows 7 but I always got an out of memory error during installation. It looks like Ubuntu only uses a small amount of memory.
  • Enable 3D Acceleration and set video memory to high.
  • Disable EFI
  • Enable IO APIC, PAE/NX, VT-x/AMD-V, Nested Paging

Start the virtual machine and boot from the eboot.iso, and then inserted the snow leopard DVD and mounted it. Then hit refresh and press the right arrow key to select it and hit enter.

Once the installation screen appears, select English and in the next screen go to the disk utilities and create a new partition on the virtual hard disk. Then install snow leopard on it.

Upgrade snow leopard and install MultiBeast

Xcode requires 10.6.3 or later. If your version is less then you’ll need to upgrade.
Download the 10.6.5 upgrade and MultiBeast to your snow leopard installation.

Install the upgrade and when it tells you to restart your computer at the end, DO NOT. Instead install MultiBeast and then restart. If you restart after the upgrade but do not install MultiBeast, then you may experience problems, like your mouse no longer working!

Installing Xcode and the iOS SDK

You can download xcode with the ios sdk from the apple website. It is a big file, around 3.5GB.
Install xcode. This should be fairly easy provided you have enough space. After installation it will take up almost 10GB!

Deploying your work to the iPhone

There are two ways to do with. The first option is to pay Apple $99. This is definitely the easiest option and probably the best if you are sure you will release something to the Apple store.

The other option allows you to test your work for free, but it does require a jailborken iPhone.
Install AppSync on your iPhone via Cydia.
In snow leopard

Applications > Utilities > Keychain Access
Certificate Assistant > Create a Certificate
Create new certificate

Name: iPhone Developer
Certificate Type: Code Signing

Accept defaults for everything else and click continue until certificate is created

Edit /Developer/Platforms/iPhoneOS.platform/Info.plist
Replace all instances of XCiPhoneOSCodeSignContext with XCCodeSignContext

In xcode: Project > Edit Project Settings > Build
Set code signing identity to the certificate you just created.

Also, to deploy for earlier version of iOS, like iOS X 4.1. Change deployment version

Setting up a shared folder
You’ll probably want to transfer files from Linux to snow leopard at some stage. The easiest option is to use NFS.

sudo apt-get install nfs-kernel-server
vim /etc/exports

I added the following line to the exports file. The * means anyone can mount it.

/home/your_name/shared_dir_on_host    *(rw,insecure,no_subtree_check)

Ideally you would want something like this

/home/your_name/shared_dir_on_host    mac_os_host_name(rw,insecure,no_subtree_check)

But I couldn’t seem to get this to work. NFS is still quite new to me.

After editing the exports file you need to reload the settings:

sudo /etc/init.d/nfs-kernel-server restart
sudo exportfs

Now in snow leopard open a terminal and mount the shared dir:

mkdir dir_to_mount_shared_dir_on_snow_leopard
mount ubuntu_host_name:/home/your_name/shared_dir_on_host dir_to_mount_shared_dir_on_snow_leopard

You may want to add this to a bash script for future.

Disable Screen Saver and Power Management

If snow leopard crashes after it is left alone for about 10 minutes, it could be because of the screen saver. It was in my case.

Under settings, disable the screen saver and the energy saving settings which turn off the hard drive and monitor.

Screen Resolution

Completely close Virtualbox and then enter this command from the terminal:

VBoxManage setextradata “VM name” “CustomVideoMode1″ “1280×800×32”

Replace VM name with the actual name of your virtual machine and likewise for the screen resolution.

Source: http://www.sysprobs.com/increase-mac-os-virtual-machine-screen-resolution-virtualbox-vmware-player

Sound
Go to this link and follow the instructions: http://forums.virtualbox.org/viewtopic.php?f=30&t=33358

The sound quality might not be perfect when you get it working, but it should be sufficient for development purposes.

Component Based Game Development

I recently learnt about component based game engines at http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/. But I was unsure how I should implement it.

After playing around and looking at how other people had done it, this is what I ended up with.

First I created an entity type which I could attach components too. It has a name for identification, a boolean variable to tell the Entity Manager whether it is still breathing, and 3 containers for the components. The first container is a dictionary of all attached components, the component name for the dictionary key. The second is just a list of components that need to be updated and in what order, and the third is a list of components that are actively listening to messages being sent from other components.

class Entity(object):
    def __init__(self, name):
        self.name = name
        self.alive = True
        self.components = {}
        self.component_update_order = None
        self.message_listeners = []

Next I created the components. Each component is a subclass of Component, and it passes its type, entity reference and whether it wants to listen to messages to the superclass.

class Component(object):
    def __init__(self, type, entity, register_as_listener = False):
        self.entity = entity
        entity.components[type] = self
        if register_as_listener:
            entity.message_listeners.append(self)

    def update(self):
        pass

    def handle_message(self, m_sender, m_type, m_data):
        pass

    def post_message(self, m_sender, m_type, m_data = None):
        for component in self.entity.message_listeners:
            component.handle_message(m_sender, m_type, m_data)

class SizeCom(Component):
    def __init__(self, entity, w, h):
        super(SizeCom, self).__init__('size', entity)
        self.w = w
        self.h = h

class PositionCom(Component):
    def __init__(self, entity, x, y):
        super(PositionCom, self).__init__('position', entity)
        self.x = x
        self.y = y

class MovementCom(Component):
    def __init__(self, entity, dx, dy):
        super(MovementCom, self).__init__('movement', entity)
        self.positionCom = entity.components['position']
        self.dx = dx
        self.dy = dy

    def update(self):
        self.positionCom.x += self.dx
        self.positionCom.y += self.dy

class GravityCom(Component):
    def __init__(self, entity):
        super(GravityCom, self).__init__('gravity', entity)
        self.movementCom = entity.components['movement']

    def update(self):
        self.movementCom.dy += GRAVITY_SPEED

class CollisionCom(Component):
    def __init__(self, entity):
        super(CollisionCom, self).__init__('collision', entity)
        self.positionCom = entity.components['position']
        self.sizeCom = entity.components['size']
        self.movementCom = entity.components['movement']

    def update(self):

        # ... check for collision ...

        if ground_collision:

            self.positionCom.y = 0
            self.movementCom.dy = 0

            self.post_message(self, M_GROUND_COLLISION, collision_point)

class AlwaysJumpingCom(Component):
    def __init__(self, entity, True):
        super(CollisionCom, self).__init__('always jumping', entity, True)
        self.movementCom = entity.components['movement']

    def handle_message(self, m_sender, m_type, m_data):
        if m_type == M_GROUND_COLLISION:
            self.movementCom.dy -= 20    # Time to jump in the air!

As you can see, the Always Jumping component waits for feedback of a collision using the message handler. The message handler is a great way for components to pass messages to each other without having to check if a component exists.

Next I used a factory pattern for building each object. First a new entity is created with a name, and then each component is created and attaches itself to the entity.

Then we add a component update order (if any) and attach it to the entity manager.

class Factory(object):
    @classmethod
    def build_object_with_only_position_info(cls, xpos, ypos):
        entity = Entity('object with only position info')

        p = PositionCom(entity, xpos, ypos)

        EntityManager.add_entity(entity)
        return entity

    @classmethod
    def build_platform(cls, width, height, xpos, ypos):
        entity = Entity('platform')

        p = PositionCom(entity, xpos, ypos)
        s = SizeCom(entity, width, height)

        EntityManager.add_entity(entity)
        return entity

    @classmethod
    def build_monster(cls, xpos, ypos, width, height):
        entity = Entity('monster')

        p = PositionCom(entity, xpos, ypos)
        s = SizeCom(entity, width, height)
        a = AIMovementCom(entity)
        g = GravityCom(entity)
        c = CollisionApplyClippingCom(entity)

        entity.component_update_order = (a, g, c)
        EntityManager.add_entity(entity)
        return entity

    @classmethod
    def build_player(cls, xpos, ypos):
        entity = Entity('player')

        WIDTH = 30
        HEIGHT = 60

        p = PositionCom(entity, xpos, ypos)
        s = SizeCom(entity, WIDTH, HEIGHT)
        m = PlayerMovementCom(entity)
        g = GravityCom(entity)
        c = CollisionApplyClippingCom(entity)

        entity.component_update_order = (m, g, c)
        EntityManager.add_entity(entity)
        return entity

    @classmethod
    def build_bullet(cls, xpos, ypos, dx):
        entity = Entity('bullet')

        WIDTH = 10
        HEIGHT = 4

        p = PositionCom(entity, xpos, ypos)
        s = SizeCom(entity, WIDTH, HEIGHT)
        m = MovementCom(entity, dx, 0)
        d = DestroyWhenOutsideCamCom(entity)
        c = CollisionDestroyMonsterCom(entity)

        entity.component_update_order = (m, d, c)
        EntityManager.add_entity(entity)
        return entity

    @classmethod
    def build_deadly_bouncing_ball(cls, xpos, ypos):
        entity = Entity('deadly bouncing ball')

        WIDTH = 10
        HEIGHT = 10

        p = PositionCom(entity, xpos, ypos)
        s = SizeCom(entity, WIDTH, HEIGHT)
        m = MovementCom(entity, 0, 0)
        g = GravityCom(entity)
        j = AlwaysJumpingCom(entity)

        entity.component_update_order = (m, g, j)
        EntityManager.add_entity(entity)
        return entity

And here is the Entity Manager. During every update, the entity manager will call each entity’s components in the order specified.

class EntityManager(object):
    entities = []
    updateable_entites = []

    @classmethod
    def add_entity(cls, entity):
        cls.entities.append(entity)

        if entity.component_update_order != None:
            cls.updateable_entites.append(entity)

        EventManager.post_event(ET_ENTITY, E_NEW_ENTITY, entity)

    @classmethod
    def remove_entity(cls, entity):
        cls.entities.remove(entity)

    @classmethod
    def update(cls):
        cls._update_entities()
        cls._remove_dead_entities()

    @classmethod
    def _update_entities(cls):
        for entity in cls.updateable_entites:
            if entity.alive:
                for component in entity.component_update_order:
                    component.update()

    @classmethod
    def _remove_dead_entities(cls):
        dead_entities = []

        for entity in cls.entities:
                dead_entities.append(entity)

                if entity.component_update_order != None:
                    cls.updateable_entites.remove(entity)

                cls.entities.remove(entity)     # R.I.P

        EventManager.post_event(ET_ENTITY, E_ENTITIES_DESTROYED, dead_entities)

The dead entities are removed at the end of every update call. For performance you could remove dead entities a little less frequently.

Also this code is setup to follow the Model-View-Controller architecture, so I have another manager called Entity Representation Manager. Each time a new entity is added it is sent to the Entity Representation Manager via the Event Manager. Then a factory called Representation Factory is called to build a sprite for the entity. The factory will lookup the entity’s name info to determine which subclass of Entity Representation should be called.

This entity representation is only rendered while the entity is alive and when the dead entities are removed from the entity manager, the same will happen in the Entity Representation Manager via the Event Manager again.

As you can see only the model uses components, whereas the view uses a typical class hierarchy because for my game there are only going to be about 5 different Representation Entities used. Depending on the situation, you could also use a component based approach for the view. You could also add a representation component to the entity itself if you don’t mind if the model and the view and a little more connected.

Also for performance you may want to replace the entity name with a enumeration constant. You may also want to add a unique id field to the entity depending on your situation.

The dictionary keys for entity components could also be replaced with enumeration constants.

Well that’s it for now. I’m going to talk about the Model-View-Controller in another post with example code.

Please give me some feedback and let me know if this was useful, or if you think I’ve missed something.

Thanks for reading!