Vector Siege
een tower‑defense game waarin je golven vijanden tegenhoudt door torens te plaatsen. de core gameplay is: vijandengolven (waves), padvolgende AI, geldsysteem om torens te plaatsen, basis‑health en feedback (screen shake).
- Waves van vijanden: spawner stuurt automatisch golven met oplopende moeilijkheid.
- Padvolgende AI: vijanden volgen waypoints richting de basis.
- Economy: verdien geld bij kills en geef het uit aan torens.
- Base health: verliest leven als vijanden de basis bereiken; game over bij 0.
- Feedback: subtiele screen shake bij schade voor meer impactgevoel.
- EnemySpawner start golven via een coroutine en spawnt vijanden met interval.
- EnemyMovement verplaatst elke vijand naar het volgende waypoint en doet schade bij de basis.
- MoneySystem beheert saldo (Add/Spend) en update de UI.
- PlayerHealth verwerkt schade, triggert screen shake en laadt de game‑over scene.
- ScreenShake schudt de camera kort met een coroutine.
Code highlights
- Geld veilig beheren (UI up-to-date)
- Context: saldo verhogen/verlagen met UI‑update en guard op te weinig geld.
public class MoneySystem : MonoBehaviour
{
[SerializeField] private int money = 50;
[SerializeField] private Text moneyText;
public int Money => money;
void Start() => UpdateMoneyUI();
public void AddMoney(int amount)
{
money += amount;
UpdateMoneyUI();
}
public void SpendMoney(int amount)
{
if (money >= amount)
{
money -= amount;
UpdateMoneyUI();
}
}
void UpdateMoneyUI()
{
moneyText.text = "FoolsGold: " + money;
}
}
- Waves spawnen met oplopende moeilijkheid
- Context: coroutine die golven start, enemies instantiëert, en snelheid/aantal aanpast.
IEnumerator SpawnWaves()
{
while (true)
{
if (waveInProgress == false)
{
// Wacht tussen golven afhankelijk van type
switch (currentWave)
{
case WaveType.Initial: yield return new WaitForSeconds(10f); break;
case WaveType.Regular: yield return new WaitForSeconds(timeBetweenWaves); break;
case WaveType.Advanced: yield return new WaitForSeconds(2f); break;
}
}
waveInProgress = true;
currentWave = GetNextWaveType(currentWave);
waveText.text = "Wave: " + currentWave;
if (currentWave == WaveType.Advanced)
{
minEnemiesPerWave += 2;
maxEnemiesPerWave += 2;
spawnWaitTime = Mathf.Max(0.05f, spawnWaitTime - 0.05f);
}
else
{
currentEnemySpeed += speedIncrement;
}
for (int i = 0; i < enemiesInThisWave; i++)
{
var enemy = Instantiate(enemyPrefab, transform.position, Quaternion.identity);
var move = enemy.GetComponent();
if (move != null)
{
move.Waypoints = waypoints;
move.Speed = (int)currentEnemySpeed;
}
yield return new WaitForSeconds(spawnWaitTime);
}
yield return new WaitUntil(AllEnemiesDestroyed);
waveInProgress = false;
UpdateEnemySpeeds(currentEnemySpeed);
}
}
- Waypoint‑navigatie en basis‑damage
- Context: verplaatsen naar huidig waypoint; bij laatste waypoint schade doen en object vernietigen.
void MoveTowardsWaypoint()
{
if (waypoints == null || waypoints.Length == 0) return;
Transform targetWaypoint = waypoints[waypointIndex];
Vector3 direction = (targetWaypoint.position - transform.position).normalized;
transform.position += direction * speed * Time.deltaTime;
if (direction.x != 0)
{
var s = transform.localScale;
s.x = Mathf.Sign(direction.x) * Mathf.Abs(s.x);
transform.localScale = s;
}
if (Vector3.Distance(transform.position, targetWaypoint.position) < 0.2f)
{
waypointIndex++;
if (waypointIndex >= waypoints.Length)
{
playerHealth?.TakeDamage(1);
Destroy(gameObject);
}
}
}
- Schade afhandelen + screen shake + game over
- Context: health verlagen, camera schudden en bij 0 health de game‑over scene laden.
public void TakeDamage(int amount)
{
currentHealth -= amount;
UpdateHealthUI();
if (screenShake != null)
StartCoroutine(screenShake.Shake(0.2f, 0.1f));
if (currentHealth <= 0)
{
Debug.Log("WASTED");
LoadGameOverScene();
}
}
- Eenvoudige, effectieve screen shake
- Context: coroutine die de camera kort en subtiel laat schudden.
public IEnumerator Shake(float duration, float magnitude)
{
Vector3 originalPosition = transform.position;
float elapsed = 0f;
while (elapsed < duration)
{
float x = Random.Range(-1f, 1f) * magnitude;
float y = Random.Range(-1f, 1f) * magnitude;
transform.position = new Vector3(originalPosition.x + x, originalPosition.y + y, originalPosition.z);
elapsed += Time.deltaTime;
yield return null;
}
transform.position = originalPosition;
}