Search This Blog

Monday, June 6, 2022

PowerShell: Making a game

Using regular PowerShell code I managed to put together a concept of a game.


Quick description of the game style:

Fighting game in which you and the computer takes turn attacking each other. When the player uses an ability this triggers a function that runs an enemy attack while your actions are blocked. The enemy action also has a bit of delay built in to make the experience a bit smoother.

Every time you deal damage, you subtract and update the health bar of the enemy while your mana is reduced as a cost of your attack. You can instead spend your turn on healing yourself or restoring mana.

Just to prove a point I put in a background image and two placeholder images from online. The player images has to be png:s with built in transparency.

The game uses classes, functions and Windows Forms. I wrote the code with PowerShell ISE, but as you can see it runs perfectly in PowerShell 7.2.4.

The following is the code I used, note that I am no programmer or skilled scripter - this was an exercise in creativity. The script uses images placed in the same folder as the game-file itself.

[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
class Player {

    [string]$name;
    [int]$age;
    [int]$hp;
    [int]$mana;
    [int]$dmg;

    [void]AddAge([int]$years){
    $this.age += $years
    }
    [void]RestoreHP(){
    $this.hp = 5;
    Write-Host "Health back to 100%"
    }
    [void]RestoreMana(){
    $this.mana = 5;
    Write-Host "Mana back to 100%"
    }
    [void]Attack(){
    $this.dmg = 1;
    Write-Host "Dealing 1 dmg"
    }

    #Player () {} # Gets overloaded by the next line of code

    Player ([string]$name,[int]$age,[int]$hp,[int]$mana,[int]$dmg){
    $this.name = $name; $this.age = $age; $this.hp = $hp; $this.mana = $mana; $this.dmg = $dmg;
    }
}

<# Create players #>
$Player1 = [Player]::New("Player1", 20, 5, 5, 1);
$Player1;

$Player2 = [Player]::New("Player2", 60, 5, 5, 1);
$Player2;

<# Create the UI#>
$MainWindow = New-Object System.Windows.Forms.Form
    $MainWindow.text = "Battle Game"
    $MainWindow.size = New-Object system.drawing.size(800,600)
    $MainWindow.FormBorderStyle = "FixedDialog"
    $MainWindow.TopMost = $True
    $MainWindow.MaximizeBox = $True
    $MainWindow.MinimizeBox = $True
    $MainWindow.ControlBox = $True
    $MainWindow.StartPosition = "CenterScreen"
    $MainWindow.font = "Arial"
    $MainWindow.TopLevel = $True
    $MainWindow.Opacity = 1
    $Image = [system.drawing.image]::FromFile("$PSScriptRoot\map.jpg")
    $MainWindow.BackgroundImageLayout = "Stretch"
    $MainWindow.BackgroundImage = $Image
    $MainWindow.BackColor = [System.Drawing.ColorTranslator]::FromHtml("#F0E68C");

$FontFace = New-Object System.Drawing.Font("Garamond",20,[System.Drawing.FontStyle]::Bold)

$Lbl_Game = New-Object System.Windows.Forms.Label
    $Lbl_Game.location = New-Object System.Drawing.Size(150,10)
    $Lbl_Game.Autosize = $true
    $Lbl_Game.ForeColor = "Red"
    $Lbl_Game.BackColor = "Black" # "Transparent"
    $Lbl_Game.Text = "Highscore Heroes - A quest for riches"
    $Lbl_Game.font = $FontFace
    $MainWindow.Controls.Add($Lbl_Game)

    
$Lbl_Player = New-Object System.Windows.Forms.Label
    $Lbl_Player.Location = New-Object System.Drawing.Size(210,200)
    $Lbl_Player.Size = New-Object System.Drawing.Size (140,20)
    $Lbl_Player.BackColor = "Black"
    $Lbl_Player.ForeColor = "Lightblue"
    $Lbl_Player.Text = "Player 1"
    $Lbl_Player.textalign = "MiddleCenter"
    $MainWindow.Controls.Add($Lbl_Player)

$Lbl_Enemy = New-Object System.Windows.Forms.Label
    $Lbl_Enemy.Location = New-Object System.Drawing.Size(410,200)
    $Lbl_Enemy.Size = New-Object System.Drawing.Size (140,20)
    $Lbl_Enemy.BackColor = "Black"
    $Lbl_Enemy.ForeColor = "Orange"
    $Lbl_Enemy.Text = "Player 2"
    $Lbl_Enemy.textalign = "MiddleCenter"
    $MainWindow.Controls.Add($Lbl_Enemy)

$Txt_Health = New-Object System.Windows.Forms.TextBox
    $Txt_Health.Location = New-Object System.Drawing.Size(210,250)
    $Txt_Health.Size = New-Object System.Drawing.Size (140,20)
    $Txt_Health.BackColor = "Black"
    $Txt_Health.ForeColor = "LightGreen"
    $Txt_Health.Text = "#" * $player1.hp
    $Txt_Health.ReadOnly = $True
    $MainWindow.Controls.Add($Txt_Health)

$Txt_Mana = New-Object System.Windows.Forms.TextBox
    $Txt_Mana.Location = New-Object System.Drawing.Size(210,270)
    $Txt_Mana.Size = New-Object System.Drawing.Size (140,20)
    $Txt_Mana.BackColor = "Black"
    $Txt_Mana.ForeColor = "Cyan"
    $Txt_Mana.Text = "#" * $player1.hp
    $Txt_Mana.ReadOnly = $True
    $MainWindow.Controls.Add($Txt_Mana)

$Txt_EnemyHealth = New-Object System.Windows.Forms.TextBox
    $Txt_EnemyHealth.Location = New-Object System.Drawing.Size(410,250)
    $Txt_EnemyHealth.Size = New-Object System.Drawing.Size (140,20)
    $Txt_EnemyHealth.BackColor = "Black"
    $Txt_EnemyHealth.ForeColor = "LightGreen"
    $Txt_EnemyHealth.Text = "#" * $player2.hp
    $Txt_EnemyHealth.ReadOnly = $True
    $MainWindow.Controls.Add($Txt_EnemyHealth)

$Txt_EnemyMana = New-Object System.Windows.Forms.TextBox
    $Txt_EnemyMana.Location = New-Object System.Drawing.Size(410,270)
    $Txt_EnemyMana.Size = New-Object System.Drawing.Size (140,20)
    $Txt_EnemyMana.BackColor = "Black"
    $Txt_EnemyMana.ForeColor = "Cyan"
    $Txt_EnemyMana.Text = "#" * $player2.hp
    $Txt_EnemyMana.ReadOnly = $True
    $MainWindow.Controls.Add($Txt_EnemyMana)

Function player2_action {
if ($Player2.hp -gt 0) {
$Btn_RestoreHP.Enabled = $False; $Btn_RestoreMana.Enabled = $False; $Btn_Attack.Enabled = $False;
Start-Sleep -Seconds 1
$player1.hp -= 1
$Txt_Health.Text = "#" * $player1.hp
write-host "Player 2 does 1 dmg to player 1"
$player2.mana -= 1
Start-sleep -Seconds 1
$Btn_RestoreHP.Enabled = $True; $Btn_RestoreMana.Enabled = $True; $Btn_Attack.Enabled = $True;
} else {Write-Host "no action taken"}
}

$Btn_RestoreHP = New-Object System.Windows.Forms.Button
    $Btn_RestoreHP.Location = New-Object System.Drawing.Size(150,530)
    $Btn_RestoreHP.Size = New-Object System.Drawing.Size(140,20)
    $Btn_RestoreHP.TextAlign = "MiddleCenter"
    $Btn_RestoreHP.Text = "Restore health"
    $Btn_RestoreHP.Enabled = $False
    $Btn_RestoreHP.BackColor = [System.Drawing.ColorTranslator]::FromHtml("#BCB88A")
    $Btn_RestoreHP.Add_Click({
        $player1.RestoreHP()
        $Txt_Health.text = "#" * $player1.hp
    })
    $MainWindow.Controls.Add($Btn_RestoreHP)

        $Btn_RestoreMana = New-Object System.Windows.Forms.Button
    $Btn_RestoreMana.Location = New-Object System.Drawing.Size(290,530)
    $Btn_RestoreMana.Size = New-Object System.Drawing.Size(140,20)
    $Btn_RestoreMana.TextAlign = "MiddleCenter"
    $Btn_RestoreMana.Text = "Restore mana"
    $Btn_RestoreMana.Enabled = $False
    $Btn_RestoreMana.BackColor = [System.Drawing.ColorTranslator]::FromHtml("#BCB88A")
    $Btn_RestoreMana.Add_Click({
        $player1.RestoreMana()
        $Txt_Mana.text = "#" * $player1.mana
    })
    $MainWindow.Controls.Add($Btn_RestoreMana)

        $Btn_Attack = New-Object System.Windows.Forms.Button
    $Btn_Attack.Location = New-Object System.Drawing.Size(430,530)
    $Btn_Attack.Size = New-Object System.Drawing.Size(140,20)
    $Btn_Attack.TextAlign = "MiddleCenter"
    $Btn_Attack.Text = "Attack"
    $Btn_Attack.Enabled = $False
    $Btn_Attack.BackColor = [System.Drawing.ColorTranslator]::FromHtml("#BCB88A")
    $Btn_Attack.Add_Click({
        if ($player2.hp -gt 0) {
        $player1.Attack()
        $player2.hp -= 1
        $Txt_EnemyHealth.Text = "#" * $player2.hp
        $player1.mana -= 1
        $Txt_Mana.text = "#" * $player1.mana
        player2_action
        } else {
        $Btn_RestoreHP.Enabled = $False; $Btn_RestoreMana.Enabled = $False; $Btn_Attack.Enabled = $False;
        Write-Host "Enemy is dead, start a new game!"
        }
    })
    $MainWindow.Controls.Add($Btn_Attack)

    $Btn_NewGame = New-Object System.Windows.Forms.Button
    $Btn_NewGame.Location = New-Object System.Drawing.Size(10,10)
    $Btn_NewGame.Size = New-Object System.Drawing.Size(100,20)
    $Btn_NewGame.TextAlign = "MiddleCenter"
    $Btn_NewGame.Text = "New Game"
    $Btn_NewGame.BackColor = [System.Drawing.ColorTranslator]::FromHtml("#BCB88A")
    $Btn_NewGame.Add_Click({

        $Btn_RestoreHP.Enabled = $True; $Btn_RestoreMana.Enabled = $True; $Btn_Attack.Enabled = $True;
        $player1.hp = 5; $player1.mana = 5;
        $player2.hp = 5; $player2.mana = 5;
        $Txt_Health.text = "#" * $player1.hp
        $Txt_Mana.text = "#" * $player1.mana
        $Txt_EnemyHealth.text = "#" * $player2.hp
        $Txt_EnemyMana.text = "#" * $player2.mana
    })
    $MainWindow.Controls.Add($Btn_NewGame)

    <# Player Image #>
    $PlayerImg = New-Object System.Windows.Forms.PictureBox;
    $PlayerImg.Width = 140;
    $PlayerImg.Height = 200;
    $PlayerImg.BackColor = [System.Drawing.Color]::Transparent
    $PlayerImg.Location = New-Object system.drawing.point(210,300)
    $PlayerImg_file = (Split-Path -Parent $PSCommandPath) + "\hero.png";
    $PlayerImg.ImageLocation = $PlayerImg_file
    $PlayerImg.BorderStyle = 0;
    $PlayerImg.Background
    $PlayerImg.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::StretchImage;
    $MainWindow.controls.Add($PlayerImg)

    <# Enemy Image #>
    $EnemyImg = New-Object System.Windows.Forms.PictureBox;
    $EnemyImg.Width = 140;
    $EnemyImg.Height = 200;
    $EnemyImg.BackColor = [System.Drawing.Color]::Transparent
    $EnemyImg.Location = New-Object system.drawing.point(410,300)
    $EnemyImg_file = (Split-Path -Parent $PSCommandPath) + "\enemy.png";
    $EnemyImg.ImageLocation = $EnemyImg_file
    $EnemyImg.BorderStyle = 0;
    $EnemyImg.Background
    $EnemyImg.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::StretchImage;
    $MainWindow.controls.Add($EnemyImg)

    <# Show the game#>
    $MainWindow.add_shown({$MainWindow.activate()})
[void] $MainWindow.ShowDialog()

No comments:

Post a Comment