Pacman Collecting Coins

133 Views Asked by At

I tried two different way to collect coins and both didn't work. I don't know what I'm doing wrong. I'm coding in c#. Is there something I'm missing or is there something I'm supposed to do beforehand?

Here is method number 1:

            //collecting coins
            foreach(Control x in this.Controls)
            {
                if (x is PictureBox && x.Tag == "coin")
                {
                    if (((PictureBox)x).Bounds.IntersectsWith(pacman.Bounds))
                    {
                        this.Controls.Remove(x); //remove that point
                        score++; // add to the score
                    }
                }
            }

and Here is method number 2:

            //collecting coins
            foreach(Control x in this.Controls)
            {
                if (x is PictureBox)
                {
                    if ((string)x.Tag == "coin" && x.Visible == true) 
                    {
                        if (pacman.Bounds.IntersectsWith(x.Bounds))
                        {
                            score += 1;
                            x.Visible = false;
                        }
                    }
                }
            }

This is work in progress so the code is still missing some parts. Here is a bit of the source code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Pac_Man_Game_Clone
{
     public partial class Form1 : Form
     {
        bool goup, godown, goright, goleft, isGameOver;
        int score, playerSpeed, redGhostSpeed, yellowGhostSpeed, pinkGhostX, pinkGhostY;

    public Form1()
    {
        InitializeComponent();

        restGame();
    }

    private void Form1_Load(object sender, EventArgs e)
    {

    }

    private void keyisdown(object sender, KeyEventArgs e)
    {
        if(e.KeyCode == Keys.Up)
        {
            goup= true;
        }
        if(e.KeyCode == Keys.Down)
        {
            godown= true;
        }
        if(e.KeyCode == Keys.Left)
        {
            goleft= true;
        }
        if(e.KeyCode == Keys.Right)
        {
            goright= true;
        }
    }

    private void keyisup(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Up)
        {
            goup = false;
        }
        if (e.KeyCode == Keys.Down)
        {
            godown = false;
        }
        if (e.KeyCode == Keys.Left)
        {
            goleft = false;
        }
        if (e.KeyCode == Keys.Right)
        {
            goright = false;
        }
    }

    private void mainGameTimer(object sender, EventArgs e)
    {
        txtScore.Text = "Score: " + score;

        //moving pacman
        if(goleft == true)
        {
            pacman.Left -= playerSpeed;
            pacman.Image = Properties.Resources.left;
        }

        if(goright == true)
        {
            pacman.Left += playerSpeed;
            pacman.Image = Properties.Resources.right;
        }

        if(godown == true)
        {
            pacman.Top += playerSpeed;
            pacman.Image = Properties.Resources.down;
        }

        if(goup == true)
        {
            pacman.Top -= playerSpeed;
            pacman.Image = Properties.Resources.Up;
        }

        //leaving the parameters
        //left and right
        if (pacman.Left < -10)
        {
            pacman.Left = 680;
        }
        if (pacman.Left > 680)
        {
            pacman.Left = -10;
        }
        //up and down
        if (pacman.Top < -10)
        {
            pacman.Top = 550;
        }
        if (pacman.Top > 550)
        {
            pacman.Top = -10;
        }

        //collecting coins
        foreach(Control x in this.Controls)
        {
            if (x is PictureBox)
            {
                if ((string)x.Tag == "coin" && x.Visible == true) 
                {
                    if (pacman.Bounds.IntersectsWith(x.Bounds))
                    {
                        score += 1;
                        x.Visible = false;
                    }
                }
            }

            //runs through wall
            if ((string)x.Tag == "wall")
            {
                if (pacman.Bounds.IntersectsWith(x.Bounds))
                {
                    // run game over
                }
            }

            //bumps to ghost
            if ((string)x.Tag == "ghost")
            {
                if (pacman.Bounds.IntersectsWith(x.Bounds))
                {
                    // run game over
                }
            }
        }

        //moving ghosts
        redGhost.Left += redGhostSpeed;

        if (redGhost.Bounds.IntersectsWith(pictureBox1.Bounds || redGhost.Bounds.IntersectsWith(pictureBox2.Bounds))
        {
            redGhost += redGhostSpeed;
        }


        if (score == int.MaxValue)
        {
            //run game over
        }
    }

    private void restGame()
    {
        txtScore.Text = "Score: 0";
        score= 0;

        redGhostSpeed = 5;
        yellowGhostSpeed = 5;
        pinkGhostX = 5;
        pinkGhostY = 5;
        playerSpeed = 8;

        isGameOver= false;

        pacman.Left = 7;
        pacman.Top= 35;

        redGhost.Left = 219;
        redGhost.Top = 56;

        yellowGhost.Left = 450;
        yellowGhost.Top = 447;

        pinkGhost.Left = 521;
        pinkGhost.Top = 227;

        foreach(Control x in this.Controls)
        {
            if(x is PictureBox)
            {
                x.Visible= true;
            }
        }

        gameTimer.Start();

    }

    private void gameOver(string message)
    {

    }
}

}

1

There are 1 best solutions below

0
Alessandro Morvillo On

Without having the full source code and the visual tree, I can only try to understand why this isn't working. To me looks like the pacman object isn't defined in the same parent as the coins.

The bounds property is relative to the parent control as coordinate origin.

It works well if each element in the collection of controls are in at the same level of the visual tree, with the same parent. If not, intersect will hardly be true because it is checking against two different coordinate origins, and even if returns true, the position on screen could not match.

As your pacman seems to be referred somewhere else than your collection, maybe your control does not have the same parent and will unlikely have the same origin for your pacman and the coin, and the IF...ELSE will never hit. Please be sure to use the same parent for the pacman and the coins.

Another solution is to draw the game objects on a canvas using the drawing primitives, and create ad hoc objects to store the drawing rectangles. This is the preferred solution as using GDI+ objects to draw game elements doesn't perform well. If you use the canvas instead, all you must do is to update the canvas on each drawing loop with the images of your game objects. This way, you will have no issues with the visual tree of the controls.

Edit: as stated in other comments, if you succeed to hit the intersection condition, in the first version of your code you will also face exception for removing items from the collection while iterating it using foreach. In this case, the solution is to iterate the list first and add the items to a new "removedItemsList" and then iterate this new list to remove the items from the controls collection without iterate it. It's not so efficient, your second solution with visibility in my opinion is far better. It's not efficient for at least two motives: one because every time you remove a control the visual tree updated for each remaining control. Second, you must allocate a new list, and reiterate it every time you hit a coin. Visibility instead only invalidate the control render rectangle, and on the next draw routing it will be draw invisible.