Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • tie/ohj1/2023s/ohj1ht
  • ojkoykka/ohj1ht
  • lemaline/ohj-1-ht-leo
  • altuoles/ohj1ht
  • ajviitan/ohj1ht
  • esahakki/ohj1ht
  • olieemka/ohj1ht
  • keinkont/ohj1ht
  • jejojuha/ohj1ht
  • parmisee/sidotut-sielut
  • wkoskine/kolikkopeli
  • aimaasko/ohj1ht
  • rapalare/ohj1ht
  • arsepiip/ohj1ht
  • tuliat/ohj1ht
  • khlaine/ohj1ht
  • thesanos/map-harkka
  • taanlaak/ohj1ht
  • avkesti/ohj1ht
  • siniseyt/ohj1ht
  • vesal/ohj1hta
  • anhahyvo/ohj1ht
  • jcvehman/leppakerttu
  • kmjaaske/ohj1ht
  • aapiippu/ohj1ht
  • reelmann/ohj1ht
  • ijkurki/ohj1ht
  • ttkelaw/ohj1ht
  • koallaht/ohj1ht
  • vesal/ohj1ht3
  • pasaikon/ohj-1-ht
  • piipaisa/ohj1ht
  • hkoktany/ohj1ht
  • pamahete/ohj1ht
  • hvriikon/ohj1ht
  • uekolehm/ohj1ht
  • njsaari/ohj1ht
  • lampiemw/rallipeli
  • tkmeskan/ohj1ht
  • aurmirle/ohj1ht
  • grohju/ohj1ht
  • awsorri/ohj1ht
  • jamamokk/ohj1ht
  • sakksama/ohj1ht
  • levalaaa/ohj1ht
  • jpjturtu/ohj1ht
  • vvvkorhv/ohj1ht
  • torkalju/s2023ohj1ht
  • koskelju/ohj1ht
  • eimaki/ohj1ht
  • matuhakk/kauppakassi
  • ollvilhi/ohj1ht
  • nktuorin/ohj1ht
  • elpeviva/ohj1ht
  • kumpuvex/ohj-1-ht
  • mvpalola/ohj1ht
  • pasonnpe/ohj1ht
  • tornhale/ohj1ht
  • iljitesa/ohj1ht
  • ruusii/ohj1ht
  • javirjo/ohj1ht
  • katahe/ohj1ht
  • niktapli/ohj1ht
  • vaalanti/ohj1ht
  • eijuhokk/ohj1ht
  • ricroos/ohj1ht
  • jjmalizy/ohj1ht
  • kirskaxt/ohj1ht
  • haemhaat/ohj1ht
  • korhanjo/ohj1ht
  • runnjuta/ohj1ht
  • jueeasik/ddr-tetris
  • kojalewa/ohj1ht
  • vejokeso/ohj1ht
  • koskeltu/ohj1ht
  • eorhala/ohj1ht
  • kiukklju/ohj1ht
  • oneemasa/ohj1ht
  • kylmsama/ohj1ht
  • mikrkonk/ohj1ht
  • viikarma/ohj1ht
  • jesvilju/ohj1ht
  • viekataj/ohj1ht
  • eerikano/ohj1ht
  • vevejuha/ohj1ht
  • ekpakkal/ohj1ht
  • otjuahos/ohj1ht
  • rajanije/ohj1ht
  • rintahe/ohj1ht
  • mpaavola/ohj1ht
  • lalaajal/ohj1ht
  • tevesiku/ohj1ht
  • malmente/ohj1ht
  • lahdelai/ohj1ht
  • lehtlrvt/syksy-2023-project
  • tuilkark/ohj1ht
  • shurmeri/ohj1ht
  • npura/ohj1ht
  • ljkarna/ohj1ht
  • pejokarj/ohj1ht
  • hytosama/ohj1ht
  • arpevile/ohj1ht
  • tspuhari/ohj1ht
  • meematma/ohj1ht
  • msvekkel/ohj1ht
  • lskumpus/temppelirosvo
  • lskumpus/ohj1ht
  • parikkp/ohj1ht
  • oopummww/sahkonhintalaskuri
  • emjowebe/ohj1ht
  • esolin/ohj1ht
  • anjakinn/ohj1ht
  • eronenve/ohj1ht
  • kautuoee/sijottajat
  • ammarttu/seikkailupeli
  • jhkortww/ohj1ht
  • tiainela/ohj1ht
  • lajoraiv/avaruushyokkaajat
  • vjkoski/ohj1ht
  • limmakyn/ohj1ht
  • kreenk/ohj1ht
  • tynnijtt/ohj1ht
  • jovesaar/ohj1ht
  • jmsutizy/ohj-1-harjoitustyo
  • veijantt/asteroidpossu
  • krseppen/ohj1ht
  • sjlihava/ohj1ht
  • kmpaanan/ohj1ht
  • emelmann/ohj1ht
  • sasavoli/jaatelokesa
  • alarojal/take-them-all
  • huhtjyil/pysakointisimulaattori
  • ttaho/ohj1ht
  • koivulmi/omenat
  • tosajaas/ohj1ht
  • sievanee/ohj1ht
  • vavavima/ohj1ht
  • adjotuhk/ohj1ht
  • heijoshe/ohj1ht
  • sammakko/kohti-aaretonta
  • anneveka/kohti-aaretonta
  • piippoje/lentokonepeli
  • emalmale/frog-jump
  • niemlexy/ohj1ht
  • jasajuyl/ohj1ht
  • peoswasa/pirtin-puolustus
  • mzitting/ohj1ht
  • heikkiaa/ohj1ht
  • mattarma/ohj-1-ht
  • kiiskiev/ohj1ht
  • noelleht/ohj1ht
  • vtsarkka/ohj1ht
  • majuvaaj/ohj-1-ht
  • eiekuiri/ohj1ht2
  • moilanii/ohj1ht
  • jpmoilan/ohj1ht
  • lipavaxy/lipavaxy
  • varauhal/ohj1ht
  • seastrom/ohj1ht3
  • jlinnik/metsakissa
  • mipeolli/ohj1ht
  • majugroh/ohj1ht
  • aijaeeus/ohj1ht
  • anjopitk/ohj1ht
  • ulentika/ohj1ht
  • paajooni/ohj1ht
  • avfresta/ohj-1-harjoitustyo-peli
  • jueesark/ohj1ht
  • sulasaal/ohj1ht
  • tervomhj/ohj1ht
  • pelkkezz/ohj1ht
  • otjalouk/hoylaajanpaluu
  • jupeupol/ohj1ht
  • jojuhemu/ilmailusaatiedotus
  • karnlazy/ohj1ht
  • tornbeev/eetu-t-ht
  • makelkjt/ohj1ht
  • masakoiv/ohj1ht
  • jerantat/ohj1ht
  • reevirta/ohj1ht
  • junijuku/ohj1ht
  • oaaltola/ohj1ht
  • renmikta/ohj1ht
  • kuntekys/ohj1ht
  • emhaauha/ohj1ht
  • lijovest/ohj1ht
  • sjuskivs/ohj1ht
  • joohirvo/ohj1ht
  • rekallio/ohj1ht
  • tuzuneru/ohj1ht
  • jacheryy/vapaa-maailma-ht
  • salompxs/ohj1ht
  • vamavatu/peliprojekti
  • mikalese/project-color
  • vimimalu/ohj1ht
  • vehartzz/ohj1ht
  • anlutuho/vilsun-seikkailu
  • saadmikk/ohj-1-ht-2
  • topevoud/ohj1ht
  • mvhonkzz/kana-kana
  • kopperp/ohj1ht
  • jutalapp/ohj1ht
  • jejajoko/ohj1ht
  • suholaju/Webbi
  • askuisyy/ohj1ht
  • samjaajo/ohj1ht
  • penttu/ohj1ht
  • ekkoykka/ohj1ht
  • tamakark/ohj1ht
  • ckbboman/ohj1ht
  • jomuhaat/ohj-1-ht
  • tslahtin/ohj1ht
  • salmatel/ohj1ht
  • linnahee/pelastapeikoilta
  • pirhonmx/ohj1ht
  • perkem/ohj1ht
  • ssniinim/ohj-1-ht
  • nikaleko/ajope
  • heijohra/ohj1ht
  • kaikkoju/ohj1ht
  • rekanyys/ohj1ht
  • nijomagg/ohj1ht
  • solismpa/ohj1ht
  • enhekorp/ohj1ht
  • myahsumy/h-tohj-1
  • nynalynn/ohj1ht
  • iitojopi/ohj1ht
  • harmjosa/ohj1ht
  • joalsaun/ohj-1-ht
  • jimsebna/ohj1ht
  • jcmbergg/ohj1ht
  • vemaveij/ohj-1-ht
232 results
Show changes
using Jypeli;
using static Jypeli.Game;
using System;
using System.Collections.Generic;
using System.Linq;
/// @author Micke Saarnela
/// @version 11.10.2023
///
/// <summary>
/// Jyväskylän yliopiston Ohjelmointi 1 -kurssin harjoitustyö, syksy 2023.
/// </summary>
namespace Superpallo3000
{
/// <summary>
/// Elämänäytön luokka (esittää pelaajan "elämien" määrän symboleina)
/// </summary>
class Symbolinaytto : GameObject
{
/// <summary>
/// OlionTilanne tilanne kertoo, missä kohtaa olion koodin suoritus on menossa.
/// </summary>
///
/// <remarks>
/// <code>
/// Normaali = olio on luotu tai animaatio on suoritettu loppuun
/// Lopetusanimaatio = olio suorittaa animaatiota
/// </code>
/// </remarks>
private enum OlionTilanne : int { Normaali, Lopetusanimaatio }
/// <summary>
/// Lopetusanimaatiossa pallon kokoa pienennetään tämän kertoimen mukaan.
/// </summary>
private const float LOPETUSANIMAATIO_KOON_KERROIN = 0.9f;
/// <summary>
/// Animaatio lopetetaan kun pallon koko on pienempi.
/// </summary>
private const float LOPETUSANIMAATIO_PIENIN_KOON_KERROIN = 0.1f;
/// <summary>
/// Varjokuvan siirto pikseleinä vaakasuunnassa symboliin verrattuna.
/// </summary>
private const int VARJON_SIIRTO_VAAKASUUNNASSA = -3;
/// <summary>
/// Varjokuvan siirto pikseleinä pystysuunnassa symboliin verrattuna.
/// </summary>
private const int VARJON_SIIRTO_PYSTYSUUNNASSA = -3;
/// <summary>
/// Miten symbolit tasataan niille varattuun tilaan.
/// </summary>
/// <remarks>Vasemmalle, Oikealle, Keskelle</remarks>
private readonly Tasaus tasaus;
/// <summary>
/// Symbolin kuva.
/// </summary>
private readonly Image symbolinKuva;
/// <summary>
/// Symbolin varjon kuva.
/// </summary>
private readonly Image symbolinVarjonKuva;
/// <summary>
/// Yhden symbolin leveys pikseleinä.
/// </summary>
private readonly int symbolinLeveys;
/// <summary>
/// Yhden symbolin korkeus pikseleinä.
/// </summary>
private readonly int symbolinKorkeus;
/// <summary>
/// Symbolien väliin jätettävä tyhjä tila pikseleinä.
/// </summary>
private readonly int symbolienValinenMarginaali;
/// <summary>
/// Symbolien esittämiseen varatun tilan leveys pikseleinä.
/// </summary>
private readonly int symbolinaytonLeveys;
/// <summary>
/// Symboleille varatun tilan keskipiste x-akselilla.
/// </summary>
private readonly int symbolinaytonKeskipisteX;
/// <summary>
/// Symboleille varatun tilan keskipiste y-akselilla.
/// </summary>
private readonly int symbolinaytonKeskipisteY;
/// <summary>
/// Olion tilanne
/// </summary>
/// <remarks>Normaali, Lopetusanimaatio</remarks>
private OlionTilanne olionTilanne = OlionTilanne.Normaali;
/// <summary>
/// Jokaisesta symbolista luodaan oma GameObject-luokan olio,
/// joka tallennetaan List-tyypin muuttujaan.
/// </summary>
private List<GameObject> symbolioliot = new List<GameObject>();
/// <summary>
/// Jokaisen symbolin varjosta luodaan oma GameObject-luokan olio,
/// joka tallennetaan List-tyypin muuttujaan.
/// </summary>
private List<GameObject> varjoOliot = new List<GameObject>();
/// <summary>
/// Tähän listaan siirretään kaikki symboli- ja varjo-oliot jotka poistetaan (animoidaan)
/// </summary>
private List<GameObject> poistettavatOliot = new List<GameObject>();
/// <summary>
/// Pääohjelma kuuntelee tämän tapahtumankäsittelijän lähettämiä viestejä.
/// </summary>
/// <remarks>Viesti lähetetään kun animaatio on valmis.</remarks>
public event EventHandler SymbolinayttoValmis;
/// <summary>
/// Luokan konstruktori.
/// </summary>
/// <param name="x">Symboleille varatun tilan keskipiste x-akselilla.</param>
/// <param name="y">Symboleille varatun tilan keskipiste y-akselilla.</param>
/// <param name="symbolinaytonLeveys">Symbolien esittämiseen varatun tilan leveys pikseleinä.</param>
/// <param name="symbolinLeveys">Yhden symbolin leveys pikseleinä.</param>
/// <param name="symbolinKorkeus">Yhden symbolin korkeus pikseleinä.</param>
/// <param name="kuva">Symbolin kuva.</param>
/// <param name="varjokuva">Symbolin varjon kuva.</param>
/// <param name="marginaali">Symbolien väliin jätettävä tyhjä tila pikseleinä.</param>
/// <param name="kpl">Kuinka monta symbolia näytetään.</param>
/// <param name="tasaus">Miten symbolit tasataan niille varattuun tilaan.</param>
public Symbolinaytto(int x, int y, int symbolinaytonLeveys, int symbolinLeveys, int symbolinKorkeus, Image kuva, Image varjokuva, int marginaali, int kpl, Tasaus tasaus) : base(0, 0)
{
if (kpl < 0) kpl = 0;
symbolinaytonKeskipisteX = x;
symbolinaytonKeskipisteY = y;
this.symbolinLeveys = symbolinLeveys;
this.symbolinKorkeus = symbolinKorkeus;
symbolinKuva = kuva;
symbolinVarjonKuva = varjokuva;
symbolienValinenMarginaali = marginaali;
this.tasaus = tasaus;
this.symbolinaytonLeveys = symbolinaytonLeveys;
}
/// <summary>
/// Päivitetään symbolien määrä.
/// </summary>
/// <param name="kpl">Uusi symbolien määrä.</param>
public void PaivitaSymbolienMaara(int kpl)
{
if (kpl < 0) kpl = 0;
int erotus = kpl - symbolioliot.Count();
if (erotus == 0) return;
if (kpl == 0 && symbolioliot.Count() > 0)
{
// poistetaan kaikki symbolit
olionTilanne = OlionTilanne.Lopetusanimaatio;
foreach (var item in symbolioliot)
{
// lisätään objekti animoitavien listaan
poistettavatOliot.Add(item);
}
symbolioliot.Clear();
foreach (var item in varjoOliot)
{
// lisätään objekti animoitavien listaan
poistettavatOliot.Add(item);
}
varjoOliot.Clear();
return;
}
if (erotus > 0)
{
// lisätään symboleita listan loppuun
for (int i = 0; i < erotus; i++)
{
symbolioliot.Add(new GameObject(symbolinLeveys, symbolinKorkeus));
int indeksi = symbolioliot.Count() - 1;
symbolioliot[indeksi].Image = symbolinKuva;
Instance.Add(symbolioliot[indeksi], (int)OlioidenPiirtotasot.UI);
// varjo
varjoOliot.Add(new GameObject(symbolinLeveys, symbolinKorkeus));
varjoOliot[indeksi].Image = symbolinVarjonKuva;
Instance.Add(varjoOliot[indeksi], (int)OlioidenPiirtotasot.UIvarjot);
}
}
else
{
// vähennetään symboleita listan loppupäästä
olionTilanne = OlionTilanne.Lopetusanimaatio;
for (; erotus < 0; erotus++)
{
// lisätään objekti animoitavien listaan
poistettavatOliot.Add(symbolioliot.Last());
symbolioliot.RemoveAt(symbolioliot.Count() - 1);
poistettavatOliot.Add(varjoOliot.Last());
varjoOliot.RemoveAt(varjoOliot.Count() - 1);
}
}
// lasketaan jokaiselle symbolille uusi koordinaatti
int symbolienLeveysYhteensa = kpl * (symbolinLeveys + symbolienValinenMarginaali) - symbolienValinenMarginaali;
int ensimmainenKoordinaattiX = 0;
switch (tasaus)
{
case Tasaus.Vasemmalle:
ensimmainenKoordinaattiX = symbolinaytonKeskipisteX - symbolinaytonLeveys / 2 + symbolinLeveys / 2;
break;
case Tasaus.Oikealle:
ensimmainenKoordinaattiX = symbolinaytonKeskipisteX + symbolinaytonLeveys / 2 - symbolienLeveysYhteensa + symbolinLeveys / 2;
break;
default:
ensimmainenKoordinaattiX = symbolinaytonKeskipisteX - symbolienLeveysYhteensa / 2 + symbolinLeveys / 2;
break;
}
for (int i = 0; i < symbolioliot.Count(); i++)
{
symbolioliot[i].X = ensimmainenKoordinaattiX + i * (symbolinLeveys + symbolienValinenMarginaali);
symbolioliot[i].Y = symbolinaytonKeskipisteY;
varjoOliot[i].X = symbolioliot[i].X + VARJON_SIIRTO_VAAKASUUNNASSA;
varjoOliot[i].Y = symbolioliot[i].Y + VARJON_SIIRTO_PYSTYSUUNNASSA;
}
if (olionTilanne != OlionTilanne.Lopetusanimaatio) SymbolinayttoValmis?.Invoke(this, EventArgs.Empty);
}
/// <summary>
/// Tuhotaan symbolit, varjot ja tämä olio.
/// </summary>
public override void Destroy()
{
foreach (var item in symbolioliot)
{
item.Destroy();
}
symbolioliot.Clear();
foreach (var item in varjoOliot)
{
item.Destroy();
}
varjoOliot.Clear();
foreach (var item in poistettavatOliot)
{
item.Destroy();
}
poistettavatOliot.Clear();
base.Destroy();
}
/// <summary>
/// Jypeli kutsuu tätä funktiota tietyin ajoin.
/// Päivitetään symbolin animaatio.
/// </summary>
/// <param name="time">Aika joka on kulunut viimeisen kutsun jälkeen.</param>
public override void Update(Time time)
{
if (IsDestroyed) { }
else if (olionTilanne == OlionTilanne.Lopetusanimaatio)
{
if (poistettavatOliot.Count() > 0)
{
// käydään läpi oliot listan lopusta alkuun,
// koska jotkut oliot poistetaan ja se muuttaa listan indeksiä
for (int i = poistettavatOliot.Count() - 1; i >= 0; i--)
{
poistettavatOliot[i].Size = poistettavatOliot[i].Size * LOPETUSANIMAATIO_KOON_KERROIN;
if (poistettavatOliot[i].Size.X < LOPETUSANIMAATIO_PIENIN_KOON_KERROIN)
{
poistettavatOliot[i].Destroy();
poistettavatOliot.RemoveAt(i);
if (poistettavatOliot.Count() == 0) break;
}
}
}
if (poistettavatOliot.Count() == 0)
{
olionTilanne = OlionTilanne.Normaali;
SymbolinayttoValmis?.Invoke(this, EventArgs.Empty);
}
}
base.Update(time);
}
}
}
using Jypeli;
using System;
/// @author Micke Saarnela
/// @version 11.10.2023
///
/// <summary>
/// Jyväskylän yliopiston Ohjelmointi 1 -kurssin harjoitustyö, syksy 2023.
/// </summary>
namespace Superpallo3000
{
/// <summary>
/// Taustakuvan luokka.
/// </summary>
/// <remarks>
/// Taustakuvalla on kaksi erilaista animaatiota, "ympyrän" muotoinen
/// liike, tai vieritys yhteen suuntaan.
/// </remarks>
class Taustakuva : GameObject
{
/// <summary>
/// Jos kuvion (punaisen kanavan) arvo on pienempi kuin raja-arvo,
/// pikselille annetaan uusi väri.
/// </summary>
private const int VARIMUUTOKSEN_RAJA_ARVO = 240;
/// <summary>
/// Kuinka paljon taustakuvan sijaintia "ympyrässä" muutetaan per Update-funktion kutsu.
/// </summary>
private const double KULMAN_MUUTOS_PER_PAIVITYS = 0.005d;
/// <summary>
/// Kuinka nopeasti taustakuvaa vieritetään lineaarisesti.
/// </summary>
private const double VIERITYKSEN_NOPEUS = 2.0d;
/// <summary>
/// Vierityksen suuntavektori.
/// </summary>
private Vector vierityksenSuunta = Vector.Zero;
/// <summary>
/// Annetun kuvion leveys pikseleinä.
/// </summary>
private int kuvionLeveys;
/// <summary>
/// Annetun kuvion korkeus pikseleinä.
/// </summary>
private int kuvionKorkeus;
/// <summary>
/// Apumuuttuja, käytetään taustakuvan animointiin.
/// </summary>
private double kulma = 0;
/// <summary>
/// Apumuuttuja, taustakuvalle annettava värisävy.
/// </summary>
private Color varisavy;
/// <summary>
/// Luokan konstruktori.
/// </summary>
/// <remarks>
/// Ohjelman ajon aikana luodaan vain yksi taustakuva-luokan olio,
/// jolle annetaan uusi kuvio aina kun kenttä vaihtuu.
/// </remarks>
public Taustakuva() : base(0, 0) {}
/// <summary>
/// Muodostetaan uusi taustakuva annetusta kuviosta.
/// </summary>
/// <param name="kohdealueenLeveys">Ikkunan leveys pikseleinä.</param>
/// <param name="kohdealueenKorkeus">Ikkunan korkeus pikseleinä.</param>
/// <param name="kuvio">Kuvion kuva.</param>
/// <param name="skaalaus">Kuvion skaalaus (oletusarvo 1.0).</param>
/// <param name="haluttuVarisavy">Kuviolle annettava värisävy (ei pakollinen).</param>
public void AsetaTaustakuva(int kohdealueenLeveys, int kohdealueenKorkeus, Image kuvio, float skaalaus = 1.0f, Color? haluttuVarisavy = null)
{
// täytetään koko taustakuvan pinta-ala kuviolla
if (skaalaus < 0) skaalaus = 0;
if (haluttuVarisavy != null && haluttuVarisavy is Color)
{
varisavy = (Color)haluttuVarisavy;
}
Image = kuvio.Clone();
Image.Rescale((int)(Image.Width * skaalaus), (int)(Image.Height * skaalaus));
Image.ApplyPixelOperation(Pikselioperaatio);
kuvionLeveys = Image.Width;
kuvionKorkeus = Image.Height;
// taustakuvan leveyden pitää olla vähintään kohdealueen leveys + 2 * kuvion leveys,
// jotta taustakuvaa voidaan liikuttaa vaakasuunnassa saumattomasti
//
// esim. kohdealue on 1000 pikseliä leveä, kuvio on 300 pikseliä leveä,
// joten kuvioita tarvitaan 1000 / 300 + 3 = 3 + 3 = 6
// eli taustakuvan leveydeksi tulee 6 * 300 = 1800 pikseliä
int kuvionPiirtokerratVaakasuunnassa = kohdealueenLeveys / kuvionLeveys + 3;
int kuvionPiirtokerratPystysuunnassa = kohdealueenKorkeus / kuvionKorkeus + 3;
TextureWrapSize = new Vector(kuvionPiirtokerratVaakasuunnassa, kuvionPiirtokerratVaakasuunnassa);
int taustakuvanLeveys = kuvionPiirtokerratVaakasuunnassa * kuvionLeveys;
int taustakuvanKorkeus = kuvionPiirtokerratPystysuunnassa * kuvionKorkeus;
Size = new Vector(taustakuvanLeveys, taustakuvanKorkeus);
}
/// <summary>
/// Kuvio värisävyn muuttamiseen tarvittava apufunktio.
/// </summary>
/// <param name="vari">Pikselin väri.</param>
/// <returns>Pikselin käsitelty väri.</returns>
private Color Pikselioperaatio(Color vari)
{
// oletetaan, että kuvio on mustavalkoinen, siitä luetaan vain punaisen värin komponentti
if (vari.RedComponent < VARIMUUTOKSEN_RAJA_ARVO) return varisavy;
return vari;
}
/// <summary>
/// Annetaan taustakuvalle satunnainen suunta.
/// </summary>
public void AsetaVierityksenSuuntaSatunnaisesti()
{
vierityksenSuunta = RandomGen.NextVector(1, 1);
}
/// <summary>
/// Jypeli kutsuu tätä funktiota tietyin ajoin.
/// Päivitetään taustakuvan positio.
/// </summary>
/// <param name="time">Aika joka on kulunut viimeisen kutsun jälkeen.</param>
public override void Update(Time time)
{
if (!IsDestroyed)
{
if (vierityksenSuunta == Vector.Zero)
{
kulma += KULMAN_MUUTOS_PER_PAIVITYS;
X = (Math.Cos(kulma) * kuvionLeveys) % kuvionLeveys;
Y = (Math.Sin(kulma) * kuvionKorkeus) % kuvionKorkeus;
}
else
{
X = (X + vierityksenSuunta.X * VIERITYKSEN_NOPEUS) % kuvionLeveys;
Y = (Y + vierityksenSuunta.Y * VIERITYKSEN_NOPEUS) % kuvionKorkeus;
}
}
base.Update(time);
}
}
}
using Jypeli;
using static Jypeli.Game;
using System;
using System.Linq;
/// @author Micke Saarnela
/// @version 11.10.2023
///
/// <summary>
/// Jyväskylän yliopiston Ohjelmointi 1 -kurssin harjoitustyö, syksy 2023.
/// </summary>
namespace Superpallo3000
{
/// <summary>
/// Pelin kenttänumeron ja pistelaskurin tarvitsema luokka.
/// Käytetään myös loppuruudun tekstien esittämiseen.
/// </summary>
class Tekstinaytto : GameObject
{
/// <summary>
/// OlionTilanne tilanne kertoo, missä kohtaa olion koodin suoritus on menossa.
/// </summary>
///
/// <remarks>
/// <code>
/// Normaali = olio on luotu tai animaatio on suoritettu loppuun
/// Animaatio = olio suorittaa animaatiota
/// JatkuvaAnimaatio = olio suorittaa jatkuvaa animaatiota
/// </code>
/// </remarks>
private enum OlionTilanne : int { Normaali, Animaatio, JatkuvaAnimaatio }
/// <summary>
/// Animaation kesto millisekunteina.
/// </summary>
private const double ANIMAATION_KESTO = 300.0d;
/// <summary>
/// Tekstin värin vaihteluun viiveeseen tehtävä muutos.
/// </summary>
private const double JATKUVAN_ANIMAATION_PAIVITYSAJAN_MUUTOS = 1.0d;
/// <summary>
/// Tekstin värin vaihtelun päivitysväli.
/// </summary>
private const double JATKUVAN_ANIMAATION_PAIVITYSVALI = 2.0d;
/// <summary>
/// Tekstin värin vaihtelun viive.
/// </summary>
private const double JATKUVAN_ANIMAATION_KULUNEEN_AJAN_KERROIN = -4.0d;
/// <summary>
/// Tekstin tavallisen animaation pystysuuntainen liike pikseleinä,
/// valitaan satunnaisesti kahden numeron väliltä.
/// </summary>
private readonly int[] animaationLiikkumavaraPystysuunnassa = { -2, 2 };
/// <summary>
/// Tekstin jatkuvan animaation pystysuuntainen liike pikseleinä,
/// valitaan satunnaisesti kahden numeron väliltä.
/// </summary>
private readonly int[] jatkuvanAnimaationLiikkumavara = { -4, 4 };
/// <summary>
/// Tekstin taustaväri.
/// </summary>
private readonly Color taustavari = Color.Transparent;
/// <summary>
/// Tekstin väri valitaan satunnaisesti näistä väreistä.
/// </summary>
private readonly Color[] varit = { Color.Aquamarine, Color.Blue, Color.Aqua, Color.Azure };
/// <summary>
/// Tekstin väri silloin kun animaatiota ei ole käynnissä.
/// </summary>
private readonly Color tekstinVari = Color.Black;
/// <summary>
/// Random-luokan olio, tarvitaan Update-funktiossa.
/// </summary>
private readonly Random random = new Random();
/// <summary>
/// Olion tilanne.
/// </summary>
/// <remarks>Normaali, Animaatio, JatkuvaAnimaatio</remarks>
private OlionTilanne olionTilanne = OlionTilanne.Normaali;
/// <summary>
/// Tekstistä muodostetaan oma Label-luokan olio.
/// </summary>
private Label tekstinaytto;
/// <summary>
/// Apumuuttuja, tekstin animaatioon kulunut aika.
/// </summary>
private double kulunutAika = 0;
/// <summary>
/// Apumuuttuja, tekstin nimaation seuraava päivitysaika.
/// </summary>
private double paivitysaika = 0;
/// <summary>
/// Luokan konstruktori.
/// </summary>
/// <param name="x">Tekstin keskipiste x-akselilla.</param>
/// <param name="y">Tekstin keskipiste y-akselilla.</param>
/// <param name="leveys">Tekstille varatun tilan leveys pikseleinä.</param>
/// <param name="korkeus">Tekstille varatun tilan korkeus pikseleinä.</param>
/// <param name="kirjasin">Käytettävä kirjasin.</param>
/// <param name="kirjasimenKoko">Kirjasimen koko.</param>
/// <param name="tekstinVari">Tekstin väri.</param>
/// <param name="teksti">Näytettävä teksti merkkijonona.</param>
/// <param name="tasaus">Tekstin tasaus sille varatussa tilassa: keskelle, vasemmalle, oikealle</param>
public Tekstinaytto(int x, int y, int leveys, int korkeus, Font kirjasin, int kirjasimenKoko, Color tekstinVari, string teksti, Tasaus tasaus) : base(0, 0)
{
Color = taustavari;
X = x;
Y = y;
this.tekstinVari = tekstinVari;
tekstinaytto = new Label(leveys, korkeus);
tekstinaytto.Text = teksti;
tekstinaytto.X = x;
tekstinaytto.Y = y;
tekstinaytto.Font = kirjasin;
tekstinaytto.Font.Size = kirjasimenKoko;
tekstinaytto.TextColor = tekstinVari;
tekstinaytto.VerticalAlignment = VerticalAlignment.Center;
switch (tasaus)
{
case Tasaus.Keskelle:
tekstinaytto.HorizontalAlignment = HorizontalAlignment.Center;
break;
case Tasaus.Vasemmalle:
tekstinaytto.HorizontalAlignment = HorizontalAlignment.Left;
break;
case Tasaus.Oikealle:
tekstinaytto.HorizontalAlignment = HorizontalAlignment.Right;
break;
default:
break;
}
Instance.Add(tekstinaytto, (int)OlioidenPiirtotasot.UI);
}
/// <summary>
/// Vaihdetaan teksti.
/// </summary>
/// <param name="teksti">Uusi teksti merkkijonona.</param>
public void PaivitaTeksti(string teksti)
{
// aloitetaan animaatio, jos teksti on muuttunut
if (!tekstinaytto.Text.Equals(teksti))
{
kulunutAika = 0;
olionTilanne = OlionTilanne.Animaatio;
}
tekstinaytto.Text = teksti;
}
/// <summary>
/// Asetetaan teksti uuteen paikkaan.
/// </summary>
/// <param name="x">Tekstin keskipiste x-akselilla.</param>
/// <param name="y">Tekstin keskipiste y-akselilla.</param>
public void AsetaPaikka(int x, int y)
{
tekstinaytto.X = x;
tekstinaytto.Y = y;
}
/// <summary>
/// Annetaan kirjasimelle uusi koko.
/// </summary>
/// <param name="koko">Kirjasimen koko pikseleinä.</param>
public void AsetaFontinKoko(int koko)
{
tekstinaytto.Font.Size = koko;
}
/// <summary>
/// Vaihdetaan animaation tilaksi jatkuva värin ja position vaihtelu.
/// </summary>
public void AloitaJatkuvaAnimaatio()
{
kulunutAika = 0;
paivitysaika = 0;
olionTilanne = OlionTilanne.JatkuvaAnimaatio;
}
/// <summary>
/// Tuhoteen tekstin olio ja tämä olio.
/// </summary>
public override void Destroy()
{
tekstinaytto.Destroy();
tekstinaytto = null;
base.Destroy();
}
/// <summary>
/// Jypeli kutsuu tätä funktiota tietyin ajoin.
/// Päivitetään tekstin väri ja positio.
/// </summary>
/// <param name="time">Aika joka on kulunut viimeisen kutsun jälkeen.</param>
public override void Update(Time time)
{
if (IsDestroyed) { }
else if (olionTilanne == OlionTilanne.Animaatio)
{
kulunutAika += time.SinceLastUpdate.TotalMilliseconds;
if (kulunutAika >= ANIMAATION_KESTO)
{
olionTilanne = OlionTilanne.Normaali;
tekstinaytto.TextColor = tekstinVari;
tekstinaytto.Y = Y;
}
else
{
tekstinaytto.TextColor = varit[random.Next(varit.Count())];
tekstinaytto.Y = Y + random.Next(animaationLiikkumavaraPystysuunnassa[0], animaationLiikkumavaraPystysuunnassa[1]);
}
}
else if (olionTilanne == OlionTilanne.JatkuvaAnimaatio)
{
kulunutAika += time.SinceLastUpdate.TotalMilliseconds;
paivitysaika += JATKUVAN_ANIMAATION_PAIVITYSAJAN_MUUTOS;
if (kulunutAika >= ANIMAATION_KESTO)
{
tekstinaytto.TextColor = tekstinVari;
tekstinaytto.X = X;
tekstinaytto.Y = Y;
kulunutAika *= JATKUVAN_ANIMAATION_KULUNEEN_AJAN_KERROIN;
}
else if (kulunutAika >= 0 && paivitysaika >= JATKUVAN_ANIMAATION_PAIVITYSVALI)
{
tekstinaytto.TextColor = varit[random.Next(varit.Count())];
tekstinaytto.X = X + random.Next(jatkuvanAnimaationLiikkumavara[0], jatkuvanAnimaationLiikkumavara[1]);
tekstinaytto.Y = Y + random.Next(jatkuvanAnimaationLiikkumavara[0], jatkuvanAnimaationLiikkumavara[1]);
paivitysaika = -JATKUVAN_ANIMAATION_PAIVITYSVALI;
}
}
base.Update(time);
}
}
}
using Jypeli;
using System;
using static Jypeli.Game;
/// @author Micke Saarnela
/// @version 11.10.2023
///
/// <summary>
/// Jyväskylän yliopiston Ohjelmointi 1 -kurssin harjoitustyö, syksy 2023.
/// </summary>
namespace Superpallo3000
{
/// <summary>
/// Tiiliolion luokka.
/// </summary>
class Tiili : PhysicsObject
{
/// <summary>
/// OlionTilanne tilanne kertoo, missä kohtaa olion koodin suoritus on menossa.
/// </summary>
///
/// <remarks>
/// <code>
/// Normaali = olio on luotu tai animaatio on suoritettu loppuun
/// Lopetusanimaatio = olio suorittaa animaatiota, jonka loppumista pitää odottaa
/// </code>
/// </remarks>
private enum OlionTilanne : int { Normaali, Lopetusanimaatio }
/// <summary>
/// Lopetusanimaatiossa tiilen kokoa pienennetään tämän kertoimen mukaan.
/// </summary>
private const float LOPETUSANIMAATIO_KOON_KERROIN = 0.9f;
/// <summary>
/// Animaatio lopetetaan kun tiilen koko on pienempi.
/// </summary>
private const float ANIMAATIO_PIENIN_KOON_KERROIN = 0.1f;
/// <summary>
/// Varjokuvan siirto pikseleinä vaakasuunnassa tiileen verrattuna.
/// </summary>
private const int VARJON_SIIRTO_VAAKASUUNNASSA = -5;
/// <summary>
/// Varjokuvan siirto pikseleinä pystysuunnassa tiileen verrattuna.
/// </summary>
private const int VARJON_SIIRTO_PYSTYSUUNNASSA = -5;
/// <summary>
/// Tiilen yksilöllinen tunniste.
/// </summary>
private readonly int id;
/// <summary>
/// Tiilen tuhoamisesta saatavat pisteet.
/// </summary>
private readonly int pisteet;
/// <summary>
/// Olion tilanne.
/// </summary>
/// <remarks>Normaali, Lopetusanimaatio</remarks>
private OlionTilanne olionTilanne = OlionTilanne.Normaali;
/// <summary>
/// Varjon GameObject-olio.
/// </summary>
private GameObject varjoOlio;
/// <summary>
/// Pääohjelma kuuntelee tämän tapahtumankäsittelijän lähettämiä viestejä.
/// </summary>
/// <remarks>Viesti lähetetään kun pallo osuu tiileen.</remarks>
public event EventHandler<int> LisaaPisteita;
/// <summary>
/// Pääohjelma kuuntelee tämän tapahtumankäsittelijän lähettämiä viestejä.
/// </summary>
/// <remarks>Viesti lähetetään kun pallo osuu tiileen.</remarks>
public event EventHandler<AaniefektienTyypit> SoitaAaniefekti;
/// <summary>
/// Tiilitehdas-olio kuuntelee tämän tapahtumankäsittelijän lähettämiä viestejä.
/// </summary>
/// <remarks>Viesti lähetetään kun pallo osuu tiileen.</remarks>
public event EventHandler UusiTiiliOnTuhoutumassa;
/// <summary>
/// Tiilitehdas-olio kuuntelee tämän tapahtumankäsittelijän lähettämiä viestejä.
/// </summary>
/// <remarks>Viesti lähetetään kun tiilen lopetusanimaatio on suoritettu loppuun.</remarks>
public event EventHandler<int> TiiliTuhoutui;
/// <summary>
/// Luokan konstruktori.
/// </summary>
/// <param name="id">Yksilöllinen tunniste.</param>
/// <param name="leveys">Leveys pikseleinä.</param>
/// <param name="korkeus">Korkeus pikseleinä.</param>
/// <param name="x">Keskipiste X-akselilla.</param>
/// <param name="y">Keskipiste Y-akselilla.</param>
/// <param name="kuva">Tiilen kuva.</param>
/// <param name="varjonKuva">Tiilen varjon kuva.</param>
/// <param name="pisteet">Tiilen tuhoamisesta saatavat pisteet.</param>
public Tiili(int id, int leveys, int korkeus, int x, int y, Image kuva, Image varjonKuva, int pisteet) : base(leveys, korkeus)
{
MakeStatic(); // staattinen olio
Restitution = 1.0; // kimmoisuus, ei muuta pallon nopeutta jos arvo on 1
KineticFriction = 0;
this.id = id;
X = x;
Y = y;
Image = kuva;
this.pisteet = pisteet;
varjoOlio = new GameObject(Size.X, Size.Y);
varjoOlio.Image = varjonKuva;
varjoOlio.X = X + VARJON_SIIRTO_VAAKASUUNNASSA;
varjoOlio.Y = Y + VARJON_SIIRTO_PYSTYSUUNNASSA;
Instance.Add(varjoOlio, (int)OlioidenPiirtotasot.Varjot);
}
/// <summary>
/// Tätä funktiota kutsutaan kun pallo osuu tiileen.
/// </summary>
public void PalloTormasiTiileen()
{
IgnoresCollisionResponse = true;
olionTilanne = OlionTilanne.Lopetusanimaatio;
// lähetetään viestit
LisaaPisteita?.Invoke(this, pisteet);
SoitaAaniefekti?.Invoke(this, AaniefektienTyypit.Tiili);
UusiTiiliOnTuhoutumassa?.Invoke(this, EventArgs.Empty);
}
/// <summary>
/// Tuhotaan tiili ja sen varjo.
/// </summary>
public override void Destroy()
{
varjoOlio.Destroy();
varjoOlio = null;
base.Destroy();
}
/// <summary>
/// Jypeli kutsuu tätä funktiota tietyin välein.
/// Päivittää tiilen animaation.
/// </summary>
/// <param name="time">Aika joka on kulunut viimeisen kutsun jälkeen.</param>
public override void Update(Time time)
{
if (IsDestroyed) { }
else if (olionTilanne == OlionTilanne.Lopetusanimaatio)
{
Size = Size * LOPETUSANIMAATIO_KOON_KERROIN;
varjoOlio.Size = Size;
varjoOlio.X = X + VARJON_SIIRTO_VAAKASUUNNASSA;
varjoOlio.Y = Y + VARJON_SIIRTO_PYSTYSUUNNASSA;
if (Size.X < ANIMAATIO_PIENIN_KOON_KERROIN)
{
// lopetusanimaatio on valmis
olionTilanne = OlionTilanne.Normaali;
TiiliTuhoutui?.Invoke(this, id);
}
}
base.Update(time);
}
}
}
using Jypeli;
using System;
using System.Collections.Generic;
using System.Linq;
using static Jypeli.Game;
/// @author Micke Saarnela
/// @version 11.10.2023
///
/// <summary>
/// Jyväskylän yliopiston Ohjelmointi 1 -kurssin harjoitustyö, syksy 2023.
/// </summary>
namespace Superpallo3000
{
/// <summary>
/// Tiilitehdas-olion luokka. Luo ja poistaa tiilet pelialueelta.
/// </summary>
/// <remarks>
/// <code>
/// Käyttö pääohjelmasta:
/// 1. luodaan uusi tiilitehdasolio
/// 2. kutsutaan funktiota LisaaTiilet()
/// 3. odotetaan viestiä TiiletLisatty
/// 4. lisätään tapahtumankäsittelijät LisaaPisteita += funktio ja SoitaAaniefekti += funktio
/// (LisaaPisteita ja SoitaAaniefekti kopioituu jokaiseen tiileen, eli tiilet pitää olla tehty ennen)
/// </code>
/// </remarks>
class Tiilitehdas : GameObject
{
/// <summary>
/// OlionTilanne tilanne kertoo, missä kohtaa olion koodin suoritus on menossa.
/// </summary>
///
/// <remarks>
/// <code>
/// Normaali = olio on luotu, tai toiminto on saatu loppuun.
/// LuodaanTiilet = lisätään tiiliä pelialueelle.
/// TiiletLuotu = tiilet on luotu.
/// PoistetaanTiilet = poistetaan jäljellä olevat tiilet pelialueelta.
/// TiiletPoistettu = kaikki tiilet on poistettu.
/// </code>
/// </remarks>
private enum OlionTilanne : int { Normaali, LuodaanTiilet, TiiletLuotu, PoistetaanTiilet, TiiletPoistettu }
/// <summary>
/// Yhden tiilen leveys pikseleinä.
/// </summary>
private readonly int tiilenLeveys;
/// <summary>
/// Yhden tiilen korkeus pikseleinä.
/// </summary>
private readonly int tiilenKorkeus;
/// <summary>
/// Tiilien väliin jätettävä tyhjä tila pikseleinä.
/// </summary>
private readonly int tiilenMarginaali;
/// <summary>
/// Tiilen tuhoamisesta saatavat pisteet.
/// </summary>
private readonly int pisteetPerTiili;
/// <summary>
/// Tiilien kuvat.
/// </summary>
private readonly Image[] tiilikuvat;
/// <summary>
/// Tiilen varjon kuva.
/// </summary>
private readonly Image tiilenVarjokuva;
/// <summary>
/// Olion tilanne.
/// </summary>
/// <remarks>Normaali, LuodaanTiilet, TiiletLuotu, PoistetaanTiilet, TiiletPoistettu</remarks>
private OlionTilanne olionTilanne = OlionTilanne.Normaali;
/// <summary>
/// Tiilien maksimimäärä per kenttä.
/// </summary>
private int tiilienMaksimimaara = 1000;
/// <summary>
/// Tiilien koordinaatit tallennetaan tähän listaan,
/// josta valitaan (ja samalla poistetaan) piirrettäviä tiiliä satunnaisesti.
/// </summary>
/// <remarks>
/// taulukko = {tiilen tunnistekoodi, x-koordinaatti, y-koordinaatti}
/// </remarks>
private List<int[]> tiilienKoordinaatit = new List<int[]>();
/// <summary>
/// Kaikki tiilioliot tallennetaan tähän muuttujaan.
/// </summary>
/// <remarks>Avain on tiilen tunniste, Tiili on olio.</remarks>
private Dictionary<int, Tiili> tiilioliot = new Dictionary<int, Tiili>();
/// <summary>
/// Random-luokan olio, tarvitaan useassa funktiossa.
/// </summary>
private readonly Random random = new Random();
/// <summary>
/// Pääohjelma kuuntelee tämän tapahtumankäsittelijän lähettämiä viestejä.
/// </summary>
/// <remarks>Viesti lähetetään kun kaikki tiilet on luotu.</remarks>
public event EventHandler TiiletLuotu;
/// <summary>
/// Pääohjelma kuuntelee tämän tapahtumankäsittelijän lähettämiä viestejä.
/// </summary>
/// <remarks>Viesti lähetetään kun kaikki tiilet on poistettu.</remarks>
public event EventHandler TiiletPoistettu;
/// <summary>
/// Pääohjelma kuuntelee tämän tapahtumankäsittelijän lähettämiä viestejä.
/// </summary>
/// <remarks>Viesti lähetetään kun pelaaja on tuhonnut kaikki tiilet, eli kenttä meni läpi.</remarks>
public event EventHandler KaikkiTiiletTuhottu;
/// <summary>
/// Kun pääohjelma lisää Tiilitehdas-oliolle tapahtumankäsittelijän,
/// se kopioidaan jokaiselle tiilioliolle erikseen.
/// Tiili lähettää viestin, kun pallo osuu siihen.
/// </summary>
public event EventHandler<int> LisaaPisteita
{
add
{
foreach (var keyValuePair in tiilioliot)
{
keyValuePair.Value.LisaaPisteita += value;
}
}
remove
{
foreach (var keyValuePair in tiilioliot)
{
keyValuePair.Value.LisaaPisteita -= value;
}
}
}
/// <summary>
/// Kun pääohjelma lisää Tiilitehdas-oliolle tapahtumankäsittelijän,
/// se kopioidaan jokaiselle tiilioliolle erikseen.
/// Tiili lähettää viestin, kun pallo osuu siihen.
/// </summary>
public event EventHandler<AaniefektienTyypit> SoitaAaniefekti
{
add
{
foreach (var keyValuePair in tiilioliot)
{
keyValuePair.Value.SoitaAaniefekti += value;
}
}
remove
{
foreach (var keyValuePair in tiilioliot)
{
keyValuePair.Value.SoitaAaniefekti -= value;
}
}
}
/// <summary>
/// Luokan konstruktori.
/// </summary>
/// <param name="tiilikuvat">Tiilien kuvat taulukkona.</param>
/// <param name="tiilenVarjokuva">Tiilen varjon kuva.</param>
/// <param name="tiilenLeveys">Tiilen leveys pikseleinä.</param>
/// <param name="tiilenKorkeus">Tiilen korkeus pikseleinä.</param>
/// <param name="tiilenMarginaali">Tiilien väliin jätettävä tyhjä tila pikseleinä.</param>
/// <param name="pisteetPerTiili">Tiilen tuhoamisesta saatavat pisteet.</param>
/// <param name="tiilienMaksimimaara">Tiilien enimmäismäärä per kenttä.</param>
public Tiilitehdas(Image[] tiilikuvat, Image tiilenVarjokuva, int tiilenLeveys, int tiilenKorkeus, int tiilenMarginaali, int pisteetPerTiili, int tiilienMaksimimaara = 1000) : base(0, 0)
{
this.tiilikuvat = tiilikuvat;
this.tiilenVarjokuva = tiilenVarjokuva;
this.tiilenLeveys = tiilenLeveys;
this.tiilenKorkeus = tiilenKorkeus;
this.tiilenMarginaali = tiilenMarginaali;
this.pisteetPerTiili = pisteetPerTiili;
this.tiilienMaksimimaara = tiilienMaksimimaara;
}
/// <summary>
/// Aloitetaan tiilien lisäys pelialueelle.
/// </summary>
/// <remarks>
/// Käytössä yhdeksän erilaista "muodostelmaa",
/// joista valitaan yksi kentän numeron perusteella.
/// </remarks>
/// <param name="kentanNumero">Kentän numero.</param>
/// <param name="pelialueenLeveys">Tiilille varatun alueen leveys pikseleinä.</param>
/// <param name="pelialueenKorkeus">Tiilille varatun alueen korkeus pikseleinä.</param>
/// <param name="ikkunanKorkeus">Ikkunan korkeus pikseleinä.</param>
/// <param name="ylareunanKorkeus">Pelialueen yläreunan korkeus pikseleinä.</param>
public void LisaaTiilet(int kentanNumero, int pelialueenLeveys, int pelialueenKorkeus, int ikkunanKorkeus, int ylareunanKorkeus)
{
// lasketaan tiilille koordinaatit taulukkoon
// luodaan vähintään 1 tiili
tiilienKoordinaatit.Clear();
int tiilenID = 0;
int tiiliaVaakasuunnassa = (pelialueenLeveys - tiilenMarginaali * 2) / (tiilenLeveys + tiilenMarginaali);
int tiiliaPystysuunnassa = pelialueenKorkeus / 2 / (tiilenKorkeus + tiilenMarginaali);
if (tiiliaVaakasuunnassa <= 0 || tiiliaPystysuunnassa <= 0)
{
tiiliaVaakasuunnassa = 1;
tiiliaPystysuunnassa = 1;
}
if (tiilienMaksimimaara < 1) tiilienMaksimimaara = 1;
if (tiiliaVaakasuunnassa * tiiliaPystysuunnassa > tiilienMaksimimaara)
{
tiiliaPystysuunnassa = Math.Max(1, tiilienMaksimimaara / tiiliaVaakasuunnassa);
tiiliaVaakasuunnassa = Math.Max(1, tiilienMaksimimaara / tiiliaPystysuunnassa);
}
int tiilistonLeveys = tiiliaVaakasuunnassa * (tiilenLeveys + tiilenMarginaali) - tiilenMarginaali;
int tiilistonKorkeus = tiiliaPystysuunnassa * (tiilenKorkeus + tiilenMarginaali) - tiilenMarginaali;
int pystySiirto = Math.Max(0, ikkunanKorkeus / 2 - ylareunanKorkeus - tiilistonKorkeus);
for (int y = 0; y < tiiliaPystysuunnassa; y++)
{
for (int x = 0; x < tiiliaVaakasuunnassa; x++)
{
// peliobjektin sijainnin x- ja y-arvot tarkoittavat keskipistettä
// pelialueen origo sijaitsee (jostain syystä) pelialueen keskipisteessä
int posx = -tiilistonLeveys / 2 + x * (tiilenLeveys + tiilenMarginaali) + tiilenLeveys / 2;
int posy = pystySiirto + y * (tiilenKorkeus + tiilenMarginaali);
tiilenID++;
switch (kentanNumero % 9)
{
// kenttien numerointi alkaa ykkösestä, 9 erilaista kenttää
// tässä lasketaan "poistettavat" tiilet, eli ne tiilet,
// joita ei lisätä kenttään -> jatketaan silmukkaa (continue)
case 1:
// joka toinen tiili
if (y % 2 == 1 && x % 2 == 0 || y % 2 == 0 && x % 2 == 1) continue;
break;
case 2:
// laatikko
if (y > 0 && y < tiiliaPystysuunnassa - 1 && x > 0 && x < tiiliaVaakasuunnassa - 1) continue;
break;
case 3:
// joka toinen rivi
if (y % 2 == 1) continue;
break;
case 4:
// laatikko2
if (y % 2 == 1 && x > 0 && x < tiiliaVaakasuunnassa - 1) continue;
break;
case 5:
// joka toinen rivi
if (y % 2 == 1) continue;
break;
case 6:
// kaksi sisäkkäistä laatikkoa
if (tiiliaPystysuunnassa > 6 && tiiliaVaakasuunnassa > 6)
{
// rivi 0 ja 6 ovat täysiä rivejä
if ((y == 1 || y == 5) && x > 0 && x < tiiliaVaakasuunnassa - 1) continue; // rivi 1 & 5
if ((y == 2 || y == 4) && (x == 1 || x == tiiliaVaakasuunnassa - 2)) continue; // rivi 2 & 4
if (y == 3 && (x == 1 || x == tiiliaVaakasuunnassa - 2 || x > 2 && x < tiiliaVaakasuunnassa - 3)) continue; // rivi 3
if (y > 6) continue;
}
break;
case 7:
if (x % 2 == 1) continue; // joka toinen sarake
break;
case 8:
if ((x + y) % 3 != 0) continue; // diagonaaliviivoja
break;
default:
// täysi ruudukko
break;
}
tiilienKoordinaatit.Add(new int[] { tiilenID, posx, posy });
}
}
olionTilanne = OlionTilanne.LuodaanTiilet;
}
/// <summary>
/// Lisätään koordinaattitaulukosta yksi satunnainen tiili pelialueelle.
/// </summary>
private void LisaaTiili()
{
// luodaan yksi tiili ja lisätään se pelialueelle
// tätä funktiota kutsutaan Update-funktiosta
if (tiilienKoordinaatit.Count() == 0)
{
// kaikki tiilet on jo lisätty, jatketaan muulla ohjelmalla
olionTilanne = OlionTilanne.TiiletLuotu;
return;
}
// valitaan satunnaiset koordinaatit {tiilenID, x, y}
int indeksi = random.Next(tiilienKoordinaatit.Count());
int tiilenID = tiilienKoordinaatit[indeksi][0];
int posx = tiilienKoordinaatit[indeksi][1];
int posy = tiilienKoordinaatit[indeksi][2];
int kuvanIndeksi = random.Next(tiilikuvat.Length);
// lisätään tiili Dictionaryyn
tiilioliot.Add(tiilenID, new Tiili(tiilenID, tiilenLeveys, tiilenKorkeus, posx, posy, tiilikuvat[kuvanIndeksi], tiilenVarjokuva, pisteetPerTiili));
// lisätään tiili pelialueelle
Instance.Add(tiilioliot[tiilenID], (int)OlioidenPiirtotasot.PeliObjektit);
// lisätään tapahtumien käsittelyt
tiilioliot[tiilenID].TiiliTuhoutui += TiiliTuhoutui;
tiilioliot[tiilenID].UusiTiiliOnTuhoutumassa += UusiTiiliOnTuhoutumassa;
// poistetaan käytetty koordinaatti listasta
tiilienKoordinaatit.RemoveAt(indeksi);
}
/// <summary>
/// Aloitetaan tiilien poistaminen.
/// </summary>
public void PoistaTiilet()
{
if (tiilioliot.Count() == 0)
{
olionTilanne = OlionTilanne.TiiletPoistettu;
return;
}
olionTilanne = OlionTilanne.PoistetaanTiilet;
}
/// <summary>
/// Poistetaan yksi satunnainen tiili pelialueelta.
/// Kutsutaan vain kuin kaikki tiilet poistetaan.
/// </summary>
private void PoistaTiili()
{
if (tiilioliot.Count() == 0)
{
olionTilanne = OlionTilanne.TiiletPoistettu;
return;
}
int[] avaimet = tiilioliot.Keys.ToArray();
int avain = avaimet[random.Next(avaimet.Count())];
tiilioliot[avain].Destroy();
tiilioliot.Remove(avain);
}
/// <summary>
/// Käsitellään tiilioliolta saatu viesti.
/// Jos viimeinen tiili on tuhottu, lähetetään viesti pääohjelmalle.
/// </summary>
/// <param name="sender">Tiiliolio.</param>
/// <param name="e">Viestin parametrit.</param>
private void UusiTiiliOnTuhoutumassa(object sender, EventArgs e)
{
if (tiilioliot.Count() <= 1) KaikkiTiiletTuhottu?.Invoke(this, EventArgs.Empty);
}
/// <summary>
/// Käsitellään tiilioliolta saatu viesti.
/// </summary>
/// <param name="sender">Tiiliolio.</param>
/// <param name="id">Tiiliolion tunniste.</param>
private void TiiliTuhoutui(object sender, int id)
{
Instance.Remove(tiilioliot[id]);
tiilioliot[id].Destroy();
tiilioliot.Remove(id);
if (tiilioliot.Count() == 0)
{
// jos kaikki tiilet on tuhottu, lähetetään viesti pääohjelmalle
TiiletPoistettu?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// Jypeli kutsuu tätä funktiota tietyin välein.
/// Lisätään tai poistetaan tiiliä per päivitys.
/// </summary>
/// <param name="time">Aika joka on kulunut viimeisen kutsun jälkeen.</param>
public override void Update(Time time)
{
if (!IsDestroyed)
{
switch (olionTilanne)
{
case OlionTilanne.LuodaanTiilet:
LisaaTiili();
LisaaTiili();
break;
case OlionTilanne.TiiletLuotu:
olionTilanne = OlionTilanne.Normaali;
TiiletLuotu?.Invoke(this, EventArgs.Empty);
break;
case OlionTilanne.PoistetaanTiilet:
PoistaTiili();
PoistaTiili();
break;
case OlionTilanne.TiiletPoistettu:
olionTilanne = OlionTilanne.Normaali;
TiiletPoistettu?.Invoke(this, EventArgs.Empty);
break;
default:
break;
}
}
base.Update(time);
}
}
}
pelikuva.jpg

169 KiB

suunnitelma/Pelin_nayttokuva_iso.jpg

389 KiB

suunnitelma/esimerkkikuva.png

9.92 KiB