class Snake extends Group {
var _textures : SnakeGame.Textures;
public function new(game, textures) {
super(game);
this._textures = textures;
}
public function addSegment(x, y) {
this.create(x, y, this.length == 0 ? _textures.head : _textures.segment);
}
}
--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
To post to this group, send email to object-co...@googlegroups.com.
Visit this group at https://groups.google.com/group/object-composition.
For more options, visit https://groups.google.com/d/optout.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composition+unsub...@googlegroups.com.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
The framework classes are huge, but that I can do nothing about, I'm just using them in Contexts, and treating them struct-like (state containers or MVC models) currently. Where is the Role interaction in the Snake class code that I posted? It only calls its own method.
--
Some feedback on the use cases...
I found them a little confusing to read at first, but that might just be because of the format (i.e. "Deviation" as the first column). Overall I think you did a great job of mapping the use cases directly to contexts and roles, down to each individual step.
One thing that didn't match though was the Keyboard role in the Movement context. The use case says the Head "Asks Keyboard for its direction" and the Keyboard "Looks up the currently pressed down key (if any)", but that's not how it happens in the code. I wonder if the use case is just for an earlier version of the code and you overlooked this?
I think Egon made some good points about the mental model. So
although the code generally maps very closely to the use cases, I
think it would be worth backing up and thinking about / discussing
the use cases themselves. This is an interesting case because a
game is different than a business app...I'm not sure it would work
to write the use cases almost entirely from the end user's
perspective, which I assume is why the use cases say "Author goal"
and not "Player goal" or "User goal". While you could certainly
write use cases that primarily describe the system from the
player's perspective, a lot of important details that need to go
in the code would be missing. Still, perhaps the use cases as they
are are leaning too far in the direction of the programmer's
mental model and implementation.
Notes in no particular order:Organization by category (contexts, data, models, views and similar) tend to harm locality of ideas. At this point there isn't much code so a single folder would probably be sufficient.
Looking at code for snake, it's difficult to understand it. It's unclear whether it's grid based or smooth. It's not clear where the snake length is represented.
In Movement context, Keyboard is hardcoded. The role is "Controller", rather than Keyboard. Keyboard is the object playing the role.
Having segments logic as part of Movement context, seems weird. To me it looks like the "Movement context" is actually the "Snake".
For some reason Collisions context is also tracking and updating points. Similarly it contains FRUIT placement logic, text updating and other things. It seems very confused in what ideas it represents.
"Movement" system having own timer will probably be problematic eventually. I.e. imagine having to add bullet-time.
"Movement" system is also triggering the collision system (imagine what happens when multiple snakes are on the board). Collision, Movement, Time are all usually orthogonal.
Hello Egon, thank you, I don't think I will be able to satisfy you on this one, though. ;) Here are my comments, just remember that this is meant to be a simple game. Expanding it to multiplayer etc, would completely change the whole picture.Notes in no particular order:Organization by category (contexts, data, models, views and similar) tend to harm locality of ideas. At this point there isn't much code so a single folder would probably be sufficient.I'm doing an is/does organization here, using the DCI terms, and that will probably be the only namespacing I will do.Looking at code for snake, it's difficult to understand it. It's unclear whether it's grid based or smooth. It's not clear where the snake length is represented.True, there is no focus on a grid system. I guess it gets a bit more clear with more knowledge about the game framework, the Roles are referring to the pixel x/y of the playfield, and I let the Movement context handle the grid to view mapping, simply because that's what I have access to in the RoleObjectContract.In Movement context, Keyboard is hardcoded. The role is "Controller", rather than Keyboard. Keyboard is the object playing the role.Good point, it should definitely be Controller. Will change it.Having segments logic as part of Movement context, seems weird. To me it looks like the "Movement context" is actually the "Snake".Talked about this earlier in response to Rune.For some reason Collisions context is also tracking and updating points. Similarly it contains FRUIT placement logic, text updating and other things. It seems very confused in what ideas it represents.It follows the mental model as specified in the use case. The Game Over could be its own Context, and will probably in a larger game, but where to draw the line...
"Movement" system having own timer will probably be problematic eventually. I.e. imagine having to add bullet-time.Not a feature on the roadmap. :) This is a simple example, no other featured are planned, which reflects the system of course. Designing the system for "infinite flexibility", where every whimsical management idea must quickly be realized, could quickly lead into overengineering, the bane of many projects.
"Movement" system is also triggering the collision system (imagine what happens when multiple snakes are on the board). Collision, Movement, Time are all usually orthogonal.Movement and Collisions are closely related, I almost decided to join them together since there are interactions happening between them, like "when colliding with the fruit, the snake should grow on next move". This inter-Context communication is something I haven't seen much talk about here. I think it could imply an encompassing Context, but for now I just put it in a System Operation, to at least separate it from the interactions, so if multiple snakes is required, at least its easy to separate.
Thanks for all your feedback Matt. I agree that the deviations are a little bit messy, I didn't want to write them on the bottom in a single sentence, because there will probably be Role interactions in a deviation too. But I wanted to try the format, in comparison with the other (Library borrowing machine). And you're right, the Keyboard being asked for its direction is an oversight, I will fix that.I wanted to experiment with the use case level, putting it as how a game creator (an experienced player, but not a professional programmer) would describe the game. Then see if a programmer could "fill in the blanks" in the RoleMethods, doing some computations with help of the RoleObjectContract, fulfilling the use case that way. But the details, yes, looks a bit spread out, and I'm not happy with the Context state, which makes the Context almost like a mix of standard OOP and DCI. It's hard to avoid though, if you only want Roles as specified in the use case... Well, the search goes on, thanks for helping out!
typedef Coordinate = {
final x : Int;
final y : Int;
}
typedef State = {
final snake : {
final segments : ImmutableArray<Coordinate>;
final nextMoveTime : Float;
final currentDirection : Float;
final wantedDirection : Float;
};
final fruit : Coordinate;
final score : Int;
final hiScore : Int;
final playfield : {
final width : Int;
final height : Int;
final squareSize : Int;
}
final active : Bool;
}
role SNAKE {
var x : Int;
var y : Int;
function move(newPos);
public function moveTo(x, y) { // RoleMethod
...
move(pos);
}
}
role SNAKE {
var x : Int;
var y : Int;
public function moveTo(x, y) { // RoleMethod
...
_gameState.moveSnake(pos); // Context variable, not a Role
STATE.moveSnake(pos); // Alt. when using Roles
}
}
I think it might be a stretch to call GameView a "View" at this point,
given that it's the whole UI. Maybe just call it GameUI? I suppose it's
still mostly a View and you're still following the general idea of MVC,
but in a more traditional MVC app wouldn't there be multiple Views for
this game? Then again I don't have experience with game development so
maybe I'm mistaken here.
This seems like a clear example of a case where the Context is really
just a function. And that's why in my JS implementation, top-level
functions can be Contexts (I should also credit Egon since I originally
got this idea from him). 'context' declarations (similar to using
'class' declarations for Contexts in other languages) are only needed
for stateful Context objects that you want to keep around after the
first time you call a method on them.