====== Boldkanon med ControlP5 ======
ControlP5 er et bibliotek til Processing, som gør det nemt at lave grafiske brugerflader (GUI).
Med ControlP5 kan du hurtigt tilføje:
* Knapper
* Sliders (til at styre talværdier)
* Toggles (on/off)
* Rotor-knapper (drej for at ændre en værdi)
* ..og meget mere.
ControlP5 kan gøre dine sketches interaktive, så din bruger nemt kan ændre ting(variable) i realtid.
{{ :images:cp5_controllers.png|}}
----
* Link : https://www.sojamo.de/libraries/controlP5/
* Link : https://github.com/sojamo/controlp5?tab=readme-ov-file
----
===== Installation af ControlP5 =====
- Åbn **Processing**.
- Gå til menuen: **Sketch → Import Library → Add Library…**
- I søgefeltet skriver du: **ControlP5**
- Vælg **ControlP5** i listen og klik på **Install**
- Vent til installationen er færdig
- Nu kan du bruge **import controlP5.*;** i dine sketches
----
===== Projekt: Boldkanon =====
I dette projekt laver du et interaktivt program, hvor du kan skyde en bold mod et mål.
Du styrer vinkel (med en rotor) og styrke (med en slider), og trykker på en knap for at skyde.\\
Bolden bevæger sig under tyngdekraften, så du skal regne lidt på vinkler og styrke.\\
Det minder om klassiske computerspil så som [[https://www.dosgames.com/game/scorched-earth|Scorched Earth]] eller [[https://classicreload.com/qbasic-gorillas.html|Gorillas]] , hvor man også skal justere vinkel og styrke for at ramme sin modstander.
Formålet er at lære både programmering gennem //"Use-Modify-Create"//, du lærer at lave en interaktiv GUI og enkel fysik på en sjov måde.
* Rotor-knap: Vinkel (0–90 grader)
* Slider: Styrke (1–20)
* Knap: Shoot
* Bolden er en separat klasse med position, hastighed og bevægelse
----
===== Bold-klasse =====
class Ball {
float x, y, vx, vy;
boolean flying = false;
float radius = 20;
Ball() {
x = 50;
y = height - 50;
vx = 0;
vy = 0;
}
void shoot(float angle, float power) {
float rad = radians(angle);
vx = cos(rad) * power;
vy = -sin(rad) * power;
x = 50;
y = height - 50;
flying = true;
}
void update() {
if (flying) {
x += vx;
y += vy;
vy += 0.3; // tyngdekraft
}
}
void display() {
circle(x, y, radius);
}
boolean hitsTarget(float tx, float ty, float tw, float th) {
if (x > tx && x < tx+tw && y > ty && y < ty+th) {
flying = false;
return true;
}
return false;
}
}
Er der smartere måde at test om vi har ramt et mål?
----
===== Setup med ControlP5 =====
import controlP5.*;
ControlP5 cp5;
float angle = 45; // rotor
float power = 10; // slider
Ball ball;
void setup() {
size(600, 400);
cp5 = new ControlP5(this);
cp5.addKnob("angle")
.setPosition(50, 330)
.setRadius(40)
.setRange(0, 90)
.setValue(45);
cp5.addSlider("power")
.setPosition(180, 330)
.setSize(200, 20)
.setRange(1, 20)
.setValue(10);
cp5.addButton("shoot")
.setPosition(430, 300)
.setSize(80, 40);
ball = new Ball();
ball.y = 250;
}
Bemærk hvordan funktioner kaldes på output af funktioner. Det kaldes typisk “method chaining” (eller på dansk: kædning af metoder).
----
===== Shoot-funktion =====
void shoot() {
ball.shoot(angle, power);
}
----
==== Events i ControlP5 ====
Sådan fanger du events (hændelser) i ControlP5.
void controlEvent(ControlEvent ev) {
if (ev.isController()) {
// Gem navnet på controlleren i en variabel
String navn = ev.getController().getName();
// Vi tjekker hvilken knap eller 'control' der har afgivet en event.
if (navn.equals("shoot")) {
// vi henter værdierne 'angle' og 'power'
float angleValue = cp5.getController("angle").getValue();
float powerValue = cp5.getController("power").getValue();
println("SKUD! - angle: " + angleValue + ", Power: " + powerValue);
ball.shoot(angleValue, powerValue);
}
}
}
Forklaring:
* **controlEvent(ControlEvent ev)** bliver **automatisk** kaldt, når en komponent sender et event.
* **ev.getController().getName()** giver navnet på den komponent, der sendte eventet.
* **cp5.getController("angle").getValue();** henter værdi som controller 'angle' har.
===== Boldens bevægelse i draw() =====
void draw() {
background(220);
// mål
rect(500, height-150, 40, 40);
ball.update();
ball.display();
if (ball.hitsTarget(500, height-150, 40, 40)) {
println("Ramt!");
}
}
----
===== Øelser =====
* Ændr tyngdekraften i `Ball.update()`
* Flyt målet til en tilfældig position
* Begræns antallet af skud
* Vis vinkel med en pil
----
===== Fri opgave – Udvid projektet =====
* Flere mål (lav evt en **Target** klasse til formålet)
* Point-system
* Reset-knap
* Tilføj lyd. (Brug SoundFile library)
* Vis boldens bane (trail)
* Flere boldklasser med forskellige egenskaber (fx størrelse, hastighed)
----