Nantes Université

Skip to content
Extraits de code Groupes Projets
Valider eed3cea9 rédigé par Clovis_Leport's avatar Clovis_Leport :8ball:
Parcourir les fichiers

Partie 5

parent bedd4018
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
package main
import (
"github.com/hajimehoshi/ebiten/v2"
)
// fonction qui vérifie si le clique est sur le texte séléctionné
func ClickOnSelect(beginX float64, endX float64, beginY float64, endY float64) bool {
posX, posY := ebiten.CursorPosition()
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) || ebiten.IsMouseButtonPressed(ebiten.MouseButtonRight) {
if float64(posX) >= beginX && float64(posX) <= endX && float64(posY) >= beginY && float64(posY) <= endY {
return true
}
}
return false
}
package main
import (
"image/color"
"project-particles/config"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/text"
)
// Fonction qui affiche les textes dans la fenêtre
func Drawtext(screen *ebiten.Image, g *game) {
RobotoRegularFontF := GetFont()
var color1 color.RGBA
// Texte Collisions qui désactive et active les collisions entre les particules
if ClickOnSelect(float64(config.General.WindowSizeX-150), float64(config.General.WindowSizeX-150)+float64(len("Collisions")*15), 15, 30) && config.General.Collisions_Text_Temp > 5 {
if config.General.Collision {
config.General.Collision = false
} else {
config.General.Collision = true
}
if config.General.Collisions_Text_State == 0 {
color1 = color.RGBA{255, 255, 255, 255}
config.General.Collisions_Text_State = 1
} else {
color1 = color.RGBA{1, 105, 17, 255}
config.General.Collisions_Text_State = 0
}
config.General.Collisions_Text_Temp = 0
} else {
if config.General.Collisions_Text_State == 0 {
color1 = color.RGBA{255, 255, 255, 255}
} else {
color1 = color.RGBA{1, 105, 17, 255}
}
}
text.Draw(screen, "Collisions", RobotoRegularFontF, config.General.WindowSizeX-150, 30, color1)
// Texte Collisions qui désactive et active les collisions entre les particules et les murs
var color2 color.RGBA
if ClickOnSelect(float64(config.General.WindowSizeX-150), float64(config.General.WindowSizeX-150)+float64(len("WallRebound")*15), 45, 60) && config.General.Wall_Text_Temp > 5 {
if config.General.WallRebound {
config.General.WallRebound = false
} else {
config.General.WallRebound = true
}
if config.General.Wall_Text_State == 0 {
color2 = color.RGBA{255, 255, 255, 255}
config.General.Wall_Text_State = 1
} else {
color2 = color.RGBA{1, 105, 17, 255}
config.General.Wall_Text_State = 0
}
config.General.Wall_Text_Temp = 0
} else {
if config.General.Wall_Text_State == 0 {
color2 = color.RGBA{255, 255, 255, 255}
} else {
color2 = color.RGBA{1, 105, 17, 255}
}
}
var color3 color.RGBA
text.Draw(screen, "WallRebound", RobotoRegularFontF, config.General.WindowSizeX-150, 60, color2)
// Texte Collisions qui désactive et active la gravité
if ClickOnSelect(float64(config.General.WindowSizeX-150), float64(config.General.WindowSizeX-150)+float64(len("GravityMode")*15), 75, 90) && config.General.Gravity_Text_Temp > 5 {
if config.General.GravityMode {
config.General.GravityMode = false
} else {
config.General.GravityMode = true
}
if config.General.Gravity_Text_State == 0 {
color3 = color.RGBA{255, 255, 255, 255}
config.General.Gravity_Text_State = 1
} else {
color3 = color.RGBA{1, 105, 17, 255}
config.General.Gravity_Text_State = 0
}
config.General.Gravity_Text_Temp = 0
} else {
if config.General.Gravity_Text_State == 0 {
color3 = color.RGBA{255, 255, 255, 255}
} else {
color3 = color.RGBA{1, 105, 17, 255}
}
}
text.Draw(screen, "GravityMode", RobotoRegularFontF, config.General.WindowSizeX-150, 90, color3)
// Texte Collisions qui désactive et active le pierre, papier, ciseaux
var color4 color.RGBA
if ClickOnSelect(float64(config.General.WindowSizeX-150), float64(config.General.WindowSizeX-150)+float64(len("PRC")*15), 105, 120) && config.General.PRC_Text_Temp > 5 {
if config.General.Rps {
config.General.Rps = false
} else {
config.General.Rps = true
}
if config.General.PRC_Text_State == 0 {
color4 = color.RGBA{255, 255, 255, 255}
config.General.PRC_Text_State = 1
} else {
color4 = color.RGBA{1, 105, 17, 255}
config.General.PRC_Text_State = 0
}
config.General.PRC_Text_Temp = 0
} else {
if config.General.PRC_Text_State == 0 {
color4 = color.RGBA{255, 255, 255, 255}
} else {
color4 = color.RGBA{1, 105, 17, 255}
}
}
text.Draw(screen, "PRC", RobotoRegularFontF, config.General.WindowSizeX-150, 120, color4)
// Texte Collisions qui désactive et active le spawn des particules en forme de cercle
var color5 color.RGBA
if ClickOnSelect(float64(config.General.WindowSizeX-150), float64(config.General.WindowSizeX-150)+float64(len("CircleMod")*15), 135, 150) && config.General.Circle_Text_Temp > 5 {
if config.General.Circle_Mode {
config.General.Circle_Mode = false
config.General.SpawnRate = 0
config.General.LifeMode = false
config.General.ScaleX = 2
config.General.ScaleY = 2
} else {
config.General.Circle_Mode = true
config.General.SpawnRate = 200
config.General.LifeMode = true
config.General.ScaleX = 0.2
config.General.ScaleY = 0.2
}
if config.General.Circle_Text_State == 0 {
color5 = color.RGBA{255, 255, 255, 255}
config.General.Circle_Text_State = 1
} else {
color5 = color.RGBA{1, 105, 17, 255}
config.General.Circle_Text_State = 0
}
config.General.Circle_Text_Temp = 0
} else {
if config.General.Circle_Text_State == 0 {
color5 = color.RGBA{255, 255, 255, 255}
} else {
color5 = color.RGBA{1, 105, 17, 255}
}
}
text.Draw(screen, "CircleMod", RobotoRegularFontF, config.General.WindowSizeX-150, 150, color5)
// Augmenter ou baisser le SpawnRate avec clic droit(baisse) et clic gauche(augmente)
var color7 color.RGBA
if ClickOnSelect(float64(config.General.WindowSizeX-150), float64(config.General.WindowSizeX-150)+float64(len("SpawnRate")*15), 165, 180) && config.General.SpawnRate_Text_Temp > 5 {
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
config.General.SpawnRate += 0.1
} else {
if config.General.SpawnRate > 0 {
config.General.SpawnRate -= 0.1
}
}
color7 = color.RGBA{1, 105, 17, 255}
config.General.SpawnRate_Text_Temp = 0
} else {
color7 = color.RGBA{255, 255, 255, 255}
}
text.Draw(screen, "SpawnRate", RobotoRegularFontF, config.General.WindowSizeX-150, 180, color7)
// Texte Collisions qui augmente et baisse la Scale avec clic droit et clic gauche
var color8 color.RGBA
if ClickOnSelect(float64(config.General.WindowSizeX-150), float64(config.General.WindowSizeX-150)+float64(len("Scale")*15), 195, 210) && config.General.Scale_Text_Temp > 5 {
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
config.General.ScaleX += 0.2
config.General.ScaleY += 0.2
} else {
if config.General.ScaleX > 0 {
config.General.ScaleX -= 0.2
config.General.ScaleY -= 0.2
}
}
color8 = color.RGBA{1, 105, 17, 255}
config.General.Scale_Text_Temp = 0
} else {
color8 = color.RGBA{255, 255, 255, 255}
}
text.Draw(screen, "Scale", RobotoRegularFontF, config.General.WindowSizeX-150, 210, color8)
// Texte qui active ou desactive les particules qui spawn à l'endroit de la souris
var color9 color.RGBA
if ClickOnSelect(float64(config.General.WindowSizeX-150), float64(config.General.WindowSizeX-150)+float64(len("FollowCursor")*15), 225, 240) && config.General.FollowCursor_Temp > 15 {
if config.General.Follow_Cursor {
config.General.Follow_Cursor = false
config.General.SpawnRate = 0
config.General.ScaleX = 1
config.General.ScaleY = 1
config.General.LifeMode = false
config.General.LifeSpan = 10
config.General.RandomSpawn = true
} else {
config.General.Follow_Cursor = true
config.General.SpawnRate = 100
config.General.ScaleX = 0.5
config.General.ScaleY = 0.5
config.General.LifeMode = true
config.General.LifeSpan = 10
config.General.RandomSpawn = false
config.General.Collision = false
config.General.Rps = false
}
color9 = color.RGBA{1, 105, 17, 255}
config.General.FollowCursor_Temp = 0
if config.General.FollowCursor_Text_State == 0 {
config.General.FollowCursor_Text_State = 1
} else {
config.General.FollowCursor_Text_State = 0
}
} else {
if config.General.FollowCursor_Text_State == 0 {
color9 = color.RGBA{255, 255, 255, 255}
} else {
color9 = color.RGBA{1, 105, 17, 255}
}
}
text.Draw(screen, "FollowCursor", RobotoRegularFontF, config.General.WindowSizeX-150, 240, color9)
// Texte qui remet toutes les variables à zéro
var color10 color.RGBA = color.RGBA{255, 0, 0, 255}
if ClickOnSelect(float64(config.General.WindowSizeX-150), float64(config.General.WindowSizeX-150)+float64(len("Reset")*15), 255, 270) && config.General.Reset_Temp > 5 {
element := g.system.Content.Front()
config.General.Vict_P = false
config.General.Vict_S = false
config.General.Vict_R = false
for element != nil {
next_particle := element.Next()
g.system.Content.Remove(element)
element.Next()
element = next_particle
}
color10 = color.RGBA{255, 255, 255, 255}
config.General.SpawnRate = 0
config.General.SpawnX = config.General.WindowSizeX / 2
config.General.SpawnY = config.General.WindowSizeY / 2
config.General.LifeMode = false
config.General.Circle_Mode = false
config.General.Collision = false
config.General.Rps = false
config.General.GravityMode = false
config.General.WallRebound = true
config.General.Reset_Temp = 0
config.General.FollowCursor_Text_State = 0
config.General.Collisions_Text_State = 0
config.General.FollowCursor_Text_State = 0
config.General.Circle_Text_State = 0
config.General.Wall_Text_Temp = 0
config.General.Gravity_Text_Temp = 0
config.General.PRC_Text_Temp = 0
}
text.Draw(screen, "Reset", RobotoRegularFontF, config.General.WindowSizeX-150, 270, color10)
// Texte qui supprime toutes les particules
var color6 color.RGBA
if ClickOnSelect(float64(config.General.WindowSizeX-150), float64(config.General.WindowSizeX-150)+float64(len("Clear")*15), 285, 300) && config.General.Clear_Text_Temp > 5 {
element := g.system.Content.Front()
config.General.Vict_P = false
config.General.Vict_S = false
config.General.Vict_R = false
for element != nil {
next_particle := element.Next()
g.system.Content.Remove(element)
element.Next()
element = next_particle
}
color6 = color.RGBA{255, 255, 255, 255}
config.General.Clear_Text_Temp = 0
} else {
color6 = color.RGBA{255, 0, 0, 255}
}
text.Draw(screen, "Clear", RobotoRegularFontF, config.General.WindowSizeX-150, 300, color6)
// augmente toutes les Temps à la fin pour ne pas que le clique de la souris clique des dixaines de fois
config.General.Wall_Text_Temp++
config.General.Collisions_Text_Temp++
config.General.Gravity_Text_Temp++
config.General.PRC_Text_Temp++
config.General.Circle_Text_Temp++
config.General.Clear_Text_Temp++
config.General.SpawnRate_Text_Temp++
config.General.Scale_Text_Temp++
config.General.FollowCursor_Temp++
config.General.Reset_Temp++
}
package main
import (
"io/ioutil"
"log"
"github.com/golang/freetype/truetype"
"golang.org/x/image/font"
)
// fonction qui récupère la font
func GetFont() font.Face {
var RobotoRegularFontF font.Face
fontBytes, err := ioutil.ReadFile("assets/04B_30__.TTF")
if err != nil {
log.Fatal(err)
}
RobotoRegularFont, err := truetype.Parse(fontBytes)
if err != nil {
log.Fatal(err)
}
RobotoRegularFontF = truetype.NewFace(RobotoRegularFont, &truetype.Options{
Size: 15,
DPI: 72,
Hinting: font.HintingFull,
})
return RobotoRegularFontF
}
# SAE_Particles
Explications des variables du config.json :
!!
Pour pouvoir lancer le programme il est nécéssaire de rentrer cela dans l'invite de commande : go get github.com/golang/freetype/truetype
C'est une commande pour installer un package afin de pouvoir importer les fonts
!!
WindowTitle : correspond au titre de la fenêtre qui apparaitra au lancement du programme
WindowSizeX : correspond à la largeur en pixel de la fenêtre
......@@ -8,98 +10,21 @@ WindowSizeY : correspond à la hauteur en pixel de la fenêtre
ParticleImage : est le chemin d'accès de l'image qui représentera les particules à l'écran
Debug : est un booléen qui permet d'afficher les fps
InitNumParticles : est un entier qui définit le nombre de particules créées au lancement du programme
RandomSpawn : est un booléen qui fait apparaitre les particules à des endroits aléatoires ou non
RandomSpawn : est un booléen qui fait apparaitre les particules à des endroits aléatoires ou non
SpawnX : permet si RandomSpawn est à false de définir la position en X sur la fenêtre des particules à l'origine
SpawnY : permet si RandomSpawn est à false de définir la position en Y sur la fenêtre des particules à l'origine
SpawnRate : est un flotant qui définit le nombre de particules à créer à chaque frame exemple 0.5 en créée une toutes les 2 frames
SpeedX : définit la vitesse en X des particules c'est le nombre de pixels en X dont elles se déplacera à chaque frame
SpeedY : définit la vitesse en Y des particules c'est le nombre de pixels en Y dont elles se déplacera à chaque frame
## Getting started
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
## Add your files
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
```
cd existing_repo
git remote add origin https://gitlab.univ-nantes.fr/E228212G/sae_particles.git
git branch -M main
git push -uf origin main
```
## Integrate with your tools
- [ ] [Set up project integrations](https://gitlab.univ-nantes.fr/E228212G/sae_particles/-/settings/integrations)
## Collaborate with your team
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
- [ ] [Automatically merge when pipeline succeeds](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
## Test and Deploy
Use the built-in continuous integration in GitLab.
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
***
# Editing this README
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template.
## Suggestions for a good README
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
## Name
Choose a self-explaining name for your project.
## Description
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
## Badges
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
## Visuals
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
## Installation
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
## Usage
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
## Support
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
## Roadmap
If you have ideas for releases in the future, it is a good idea to list them in the README.
## Contributing
State if you are open to contributions and what your requirements are for accepting them.
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
## Authors and acknowledgment
Show your appreciation to those who have contributed to the project.
## License
For open source projects, say how it is licensed.
## Project status
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
ScaleX et ScaleY : Determinent l'échelle de la particule c'est la multiplication des pixels en x et y de l'image
Elasticity: est un flottant qui change la force après rebondissement d'une particule quand c'est à 1 la particule ne perd pas de vittesse, quand c'est à
0,5 elle perd 50% de sa vitesse initiale
LifeMode : est un booléen qui choisit si les particules mourront
LifeSpan : si Lifemode est à true lifespan défini le temps de vie de la particule en fonction des frames donc un lifespan de 60 fera vivre la particule 1 seconde
Vict_S, Vict_P,Vict_SR : booléen qui dit lors d'un pierre, papier, ciseaux si un des trois a gagné
Opacity_Increment : c'est un entier qui pour les fonctions increaseopacity et decreaseopacity décide de combien on augment ou baisse l'opacité à chaque appel de la fonction
Circle_Mode : booléen qui à true fait spawn des particules en cercle
Circle_Radius : choisit le rayon du cercle
Follow_Cursor : booléen qui si à true fais spawn des particules à l'endroit où est le pointeur de la souris
Tous les XXX_Text_State et XXX_Text_Temp sont des variables qui décident des états de boutons à l'écran pour désaciver en temps réel les différentes variables du config.json en ne doivent donc pas être touchées.
Fichier ajouté
package assets
import (
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
_ "image/png"
"log"
"project-particles/config"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
)
// ParticleImage est une variable globale pour stocker l'image d'une particule
var ParticleImage *ebiten.Image
var ParticleImageDef *ebiten.Image
var ParticleImage1 *ebiten.Image
var ParticleImage2 *ebiten.Image
var ParticleImage3 *ebiten.Image
// Get charge en mémoire l'image de la particule. (particle.png)
// Vous pouvez changer cette image si vous le souhaitez, et même en proposer
......@@ -18,7 +22,10 @@ var ParticleImage *ebiten.Image
// si vous avez déjà bien avancé sur tout le reste.
func Get() {
var err error
ParticleImage, _, err = ebitenutil.NewImageFromFile(config.General.ParticleImage)
ParticleImageDef, _, err = ebitenutil.NewImageFromFile(config.General.ParticleImageDef)
ParticleImage1, _, err = ebitenutil.NewImageFromFile(config.General.ParticleImage1)
ParticleImage2, _, err = ebitenutil.NewImageFromFile(config.General.ParticleImage2)
ParticleImage3, _, err = ebitenutil.NewImageFromFile(config.General.ParticleImage3)
if err != nil {
log.Fatal("Problem while loading particle image: ", err)
}
......
assets/leaf.png

173 octets

assets/pop.png

9,91 ko

assets/pop2.png

466 octets

assets/rock.png

200 octets

assets/scissors.png

192 octets

......@@ -2,14 +2,54 @@
"WindowTitle": "Project particles",
"WindowSizeX": 800,
"WindowSizeY": 600,
"ParticleImage": "assets/particle.png",
"MarginX": 50,
"MarginY" : 30,
"ParticleImageDef": "assets/particle.png",
"ParticleImage1": "assets/scissors.png",
"ParticleImage2": "assets/rock.png",
"ParticleImage3": "assets/leaf.png",
"No_Winner": true,
"Debug": true,
"InitNumParticles": 50,
"RandomSpawn":false,
"InitNumParticles": 25,
"RandomSpawn":true,
"WallRebound": true,
"Collision": true,
"GravityMode": false,
"Rps": true,
"GravityForce": -0.5,
"SpawnX": 400,
"SpawnY": 300,
"SpawnRate": 0,
"SpeedX": 5,
"SpeedY": 5
"SpeedX": 7,
"SpeedY": 7,
"ScaleX" : 5,
"ScaleY" : 5,
"Elasticity" : 1,
"LifeMode": false,
"LifeSpan" : 10,
"Vict_S" : false,
"Vict_R" : false,
"Vict_P" : false,
"Opacity_Increment" : 1,
"Circle_Mode" : false,
"Circle_Radius" : 100,
"Follow_Cursor": false,
"Wall_Text_State": 0,
"Wall_Text_Temp": 0,
"Collisions_Text_State":0,
"Collisions_Text_Temp":0,
"Gravity_Text_State": 0,
"Gravity_Text_Temp":0,
"PRC_Text_State":0,
"PRC_Text_Temp":0,
"Circle_Text_State":0,
"Circle_Text_Temp":0,
"Clear_Text_Temp":0,
"SpawnRate_Text_Temp":0,
"Scale_Text_Temp":0,
"FollowCursor_Text_State":0,
"FollowCursor_Text_Temp":0,
"Reset_Temp":0
}
......@@ -8,17 +8,45 @@ package config
// Vous pouvez ajouter des champs et ils seront automatiquement lus dans le
// fichier de config. Vous devrez le faire plusieurs fois durant le projet.
type Config struct {
WindowTitle string
WindowSizeX, WindowSizeY int
MarginX, MarginY int
ParticleImage string
Debug bool
InitNumParticles int
RandomSpawn bool
SpawnX, SpawnY int
SpawnRate float64
SpeedX int
SpeedY int
WindowTitle string
WindowSizeX, WindowSizeY int
MarginX, MarginY int
ParticleImageDef, ParticleImage1, ParticleImage2, ParticleImage3 string
Debug bool
InitNumParticles int
RandomSpawn bool
SpawnX, SpawnY int
SpawnRate float64
SpeedX float64
SpeedY float64
ScaleX, ScaleY float64
WallRebound bool
Collision bool
GravityMode bool
Rps bool
GravityForce float64
Elasticity float64
LifeMode bool
LifeSpan float64
Vict_S, Vict_R, Vict_P, No_Winner bool
Opacity_Increment, Circle_Radius float64
Circle_Mode, Follow_Cursor bool
Wall_Text_State int
Wall_Text_Temp int
Collisions_Text_State int
Collisions_Text_Temp int
Gravity_Text_State int
Gravity_Text_Temp int
PRC_Text_State int
PRC_Text_Temp int
Circle_Text_State int
Circle_Text_Temp int
Clear_Text_Temp int
SpawnRate_Text_Temp int
Scale_Text_Temp int
FollowCursor_Text_State int
FollowCursor_Temp int
Reset_Temp int
}
var General Config
......@@ -8,14 +8,17 @@ import (
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
"golang.org/x/image/font"
)
var mplusNormalFont font.Face
// Draw se charge d'afficher à l'écran l'état actuel du système de particules
// g.system. Elle est appelée automatiquement environ 60 fois par seconde par
// la bibliothèque Ebiten. Cette fonction pourra être légèrement modifiée quand
// c'est précisé dans le sujet.
func (g *game) Draw(screen *ebiten.Image) {
Drawtext(screen, g)
for e := g.system.Content.Front(); e != nil; e = e.Next() {
p, ok := e.Value.(*particles.Particle)
if ok {
......@@ -24,12 +27,21 @@ func (g *game) Draw(screen *ebiten.Image) {
options.GeoM.Scale(p.ScaleX, p.ScaleY)
options.GeoM.Translate(p.PositionX, p.PositionY)
options.ColorM.Scale(p.ColorRed, p.ColorGreen, p.ColorBlue, p.Opacity)
screen.DrawImage(assets.ParticleImage, &options)
if config.General.Rps {
if p.Skin == 1 {
screen.DrawImage(assets.ParticleImage1, &options)
} else if p.Skin == 2 {
screen.DrawImage(assets.ParticleImage2, &options)
} else if p.Skin == 3 {
screen.DrawImage(assets.ParticleImage3, &options)
}
} else {
screen.DrawImage(assets.ParticleImageDef, &options)
}
}
}
if config.General.Debug {
ebitenutil.DebugPrint(screen, fmt.Sprint(ebiten.ActualTPS()))
ebitenutil.DebugPrint(screen, fmt.Sprint(ebiten.ActualTPS(), " Nb_Part : ", g.system.Content.Len()))
}
}
......@@ -7,6 +7,7 @@ require github.com/hajimehoshi/ebiten/v2 v2.4.14
require (
github.com/ebitengine/purego v0.0.0-20220905075623-aeed57cda744 // indirect
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/hajimehoshi/file2byteslice v0.0.0-20210813153925-5340248a8f41 // indirect
github.com/jezek/xgb v1.0.1 // indirect
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 // indirect
......
package particles
import (
"math/rand"
"project-particles/config"
"time"
)
func Create_particle(i int) *Particle {
if !config.General.RandomSpawn {
rand.Seed(time.Now().UnixNano() + int64(i))
speedx := float64(-(config.General.SpeedX)) + rand.Float64()*float64(config.General.SpeedX-(-(config.General.SpeedX)))
speedy := float64(-(config.General.SpeedY)) + rand.Float64()*float64(config.General.SpeedY-(-(config.General.SpeedY)))
for speedx == 0 && speedy == 0 {
if speedx == 0 {
speedx = float64(-(config.General.SpeedX)) + rand.Float64()*float64(config.General.SpeedX-(-(config.General.SpeedX)))
} else {
speedy = float64(-(config.General.SpeedY)) + rand.Float64()*float64(config.General.SpeedY-(-(config.General.SpeedY)))
//Skin : 1 = Scissors
//Skin : 2 = Rock
//Skin : 3 = Paper
func Create_particle(particle_index int) *Particle {
if config.General.Vict_P || config.General.Vict_R || config.General.Vict_S && config.General.No_Winner {
//En cas de victoire pour le RPS, on affiche une particule en grand au centre
if config.General.Vict_S {
return &Particle{
PositionX: float64(config.General.WindowSizeX)/2 - 20*config.General.ScaleX,
PositionY: float64(config.General.WindowSizeY)/2 - 20*config.General.ScaleY,
SpeedX: 0,
SpeedY: 0,
ScaleX: 15, ScaleY: 15,
ColorRed: 1, ColorGreen: 1, ColorBlue: 1,
Opacity: 1,
Skin: 1,
}
}
return &Particle{
PositionX: float64(config.General.SpawnX),
PositionY: float64(config.General.SpawnY),
} else if config.General.Vict_R {
return &Particle{
PositionX: float64(config.General.WindowSizeX)/2 - 20*config.General.ScaleX,
PositionY: float64(config.General.WindowSizeY)/2 - 20*config.General.ScaleY,
SpeedX: 0,
SpeedY: 0,
SpeedX: speedx,
SpeedY: speedy,
ScaleX: 15, ScaleY: 15,
ColorRed: 1, ColorGreen: 1, ColorBlue: 1,
Opacity: 1,
ScaleX: 1, ScaleY: 1,
ColorRed: 1, ColorGreen: 1, ColorBlue: 1,
Opacity: 1,
}
} else {
rand.Seed(time.Now().UnixNano() + int64(i))
speedx := float64(-(config.General.SpeedX)) + rand.Float64()*float64(config.General.SpeedX-(-(config.General.SpeedX)))
speedy := float64(-(config.General.SpeedY)) + rand.Float64()*float64(config.General.SpeedY-(-(config.General.SpeedY)))
posX := 0 + rand.Intn(config.General.WindowSizeX-10)
posY := 0 + rand.Intn(config.General.WindowSizeY-10)
for speedx == 0 && speedy == 0 {
if speedx == 0 {
speedx = float64(-(config.General.SpeedX)) + rand.Float64()*float64(config.General.SpeedX-(-(config.General.SpeedX)))
} else {
speedy = float64(-(config.General.SpeedY)) + rand.Float64()*float64(config.General.SpeedY-(-(config.General.SpeedY)))
Skin: 2,
}
} else {
return &Particle{
PositionX: float64(config.General.WindowSizeX)/2 - 20*config.General.ScaleX,
PositionY: float64(config.General.WindowSizeY)/2 - 20*config.General.ScaleY,
SpeedX: 0,
SpeedY: 0,
ScaleX: 15, ScaleY: 15,
ColorRed: 1, ColorGreen: 1, ColorBlue: 1,
Opacity: 1,
Skin: 3,
}
}
}
// La variable angle est seulement utilisée en cas de mode cercle, elle permet de decider l'angle de la particule par rapport à sons cercle
angle := rand_angle(particle_index)
//C'est trois variables correspondent aux paramètres de la particule à créer et sont déterminées avec des fonctions tièrces
posX, posY := Position(angle)
speedx, speedy := Rand_Speed(particle_index)
skin_nb := Rand_Skin(particle_index)
if Outside_list.Len() < 1 {
return &Particle{
PositionX: float64(posX),
PositionY: float64(posY),
PositionX: posX,
PositionY: posY,
SpeedX: speedx,
SpeedY: speedy,
ScaleX: 1, ScaleY: 1,
ScaleX: config.General.ScaleX, ScaleY: config.General.ScaleY,
ColorRed: 1, ColorGreen: 1, ColorBlue: 1,
Opacity: 1,
Skin: skin_nb,
}
} else {
//Cette partie sers à recycler des particules toujours en mémoire mais supprimées pour éviter de saturer la mémoire
p_revive := Outside_list.Front().Value.(*Particle)
Outside_list.Remove(Outside_list.Front())
p_revive.PositionX = posX
p_revive.PositionY = posY
p_revive.SpeedX, p_revive.SpeedY = speedx, speedy
p_revive.Opacity = 1
return p_revive
}
}
package particles
import (
"container/list"
"math/rand"
"project-particles/config"
"testing"
"time"
)
//Vérification de la création correcte d'une particule
func Test_Create_1_Particle(t *testing.T) {
config.Get("../config.json")
l := list.New()
l.PushFront(Create_particle(0))
lenght := l.Len()
if lenght > 1 {
t.Error("Trop de particules créées")
} else if lenght < 1 {
t.Error("Pas assez de particules créées")
}
}
// Test de la création d'une particule placée de façon prévue, vérification de la position
func Test_Create_1_Particle_Not_Randomly_Placed(t *testing.T) {
config.Get("../config.json")
config.General.RandomSpawn = false
l := list.New()
l.PushFront(Create_particle(0))
posX := l.Front().Value.(*Particle).PositionX
posY := l.Front().Value.(*Particle).PositionY
if posX != float64(config.General.SpawnX) {
if posY != float64(config.General.SpawnY) {
t.Error("Positions X et Y incorrectes")
} else {
t.Error("Position X incorrecte")
}
} else if posY != float64(config.General.SpawnY) {
t.Error("Position Y incorrecte")
}
}
//Vérification lors du placement aléatoire d'une particule, celle-ci doit apparaître dans la fenêtre
func Test_Create_1_Particle_Randomly_Placed_Inbounds(t *testing.T) {
config.Get("../config.json")
config.General.RandomSpawn = true
l := list.New()
l.PushFront(Create_particle(0))
posX := l.Front().Value.(*Particle).PositionX
ScaleX := l.Front().Value.(*Particle).ScaleX
posY := l.Front().Value.(*Particle).PositionY
ScaleY := l.Front().Value.(*Particle).ScaleY
if posX < 0 || posX+10*ScaleX > float64(config.General.WindowSizeX) {
t.Error("Position X en dehors des limites de la fenêtre")
} else if posY < 0 || posY+10*ScaleY > float64(config.General.WindowSizeY) {
t.Error("Position Y en dehors des limites de la fenêtre")
}
}
//Création d'un nombre aléatoire de particule et verification de la bonne quantité
func Test_Create_Rand_Number_Of_Particle(t *testing.T) {
config.Get("../config.json")
l := list.New()
rand.Seed(time.Now().UnixNano())
nb := rand.Intn(10)
for i := 0; i < nb; i++ {
l.PushFront(Create_particle(i))
}
lenght := l.Len()
if lenght > nb {
t.Error("Trop de particules créées, nombre attendu : ", nb)
} else if lenght < nb {
t.Error("Pas assez de particules créées, nombre attendu : ", nb)
}
}
package particles
import "project-particles/config"
func Decrease_Opacity(particle *Particle) {
particle.Opacity -= config.General.Opacity_Increment
}
package particles
import (
"project-particles/config"
"testing"
)
// Test fonction decrease de 1 par 1
func Test_Decrease_by_1(t *testing.T) {
config.General.Opacity_Increment = 1
p1 := Particle{
PositionX: 0,
PositionY: 0,
SpeedX: 1,
SpeedY: 1,
ScaleX: 1, ScaleY: 1,
ColorRed: 1, ColorGreen: 1, ColorBlue: 1,
Opacity: 1,
}
previous_opacity := p1.Opacity
Decrease_Opacity(&p1)
if p1.Opacity != previous_opacity-1 {
t.Error("L'opacité n'est pas correctement mise à jour, différence :", previous_opacity-p1.Opacity)
}
}
// Test fonction decrease de 5 par 5
func Test_Decrease_by_5(t *testing.T) {
config.General.Opacity_Increment = 5
p1 := Particle{
PositionX: 0,
PositionY: 0,
SpeedX: 1,
SpeedY: 1,
ScaleX: 1, ScaleY: 1,
ColorRed: 1, ColorGreen: 1, ColorBlue: 1,
Opacity: 1,
}
previous_opacity := p1.Opacity
Decrease_Opacity(&p1)
if p1.Opacity != previous_opacity-5 {
t.Error("L'opacité n'est pas correctement mise à jour, différence :", previous_opacity-p1.Opacity)
}
}
// Test fonction decrease de -1 par -1
func Test_Decrease_by_Negative_1(t *testing.T) {
config.General.Opacity_Increment = -1
p1 := Particle{
PositionX: 0,
PositionY: 0,
SpeedX: 1,
SpeedY: 1,
ScaleX: 1, ScaleY: 1,
ColorRed: 1, ColorGreen: 1, ColorBlue: 1,
Opacity: 1,
}
previous_opacity := p1.Opacity
Decrease_Opacity(&p1)
if p1.Opacity != previous_opacity+1 {
t.Error("L'opacité n'est pas correctement mise à jour, différence :", previous_opacity-p1.Opacity)
}
}
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Veuillez vous inscrire ou vous pour commenter