I'm making snake game in flutter but I've got a problem. I'm changing my snake position inside gameTick method (snake variable) - working fine, then I'm generating new grid inside build method (grid variable) - working fine, and at the end build method should return widget tree. But I can't see changes at my screen. It looks like build method is building app with old grid variable.
I deleted some unrelated code. Thanks for help.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:swipe/swipe.dart';
void main() {
runApp(
MaterialApp(
title: 'snake',
theme: ThemeData(
brightness: Brightness.dark,
primaryColor: Colors.blueGrey,
),
home: Game(),
),
);
}
class Game extends StatefulWidget {
const Game({Key? key}) : super(key: key);
@override
State<Game> createState() => _GameState();
}
class _GameState extends State<Game> {
List<List<int>> snake = [
[5, 5],
[6, 5],
[7, 5]
];
List<Container> grid = List.filled(121, Container());
Timer? timer;
@override
void initState() {
Timer.periodic(Duration(seconds: 1), (Timer t) => gameTick());
super.initState();
}
@override
void dispose() {
timer?.cancel();
super.dispose();
}
void gameTick() {
for (List<int> pair in snake) {
setState(
() {
pair[0]--;
},
);
}
}
@override
Widget build(BuildContext context) {
for (int i = 0; i < 121; i ) {
int row = (i / 11).floor();
int col = i % 11;
for (List<int> pair in snake) {
int snakeRow = pair[0];
int snakeCol = pair[1];
if ((snakeRow == row) && (snakeCol == col)) {
grid[i] = Container(
decoration: BoxDecoration(
color: Colors.greenAccent,
border: Border.all(color: Color(0xFF383434), width: 2),
),
);
break;
} else {
grid[i] = Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.greenAccent, width: 2),
),
);
}
}
}
return Scaffold(
body: SizedBox.expand(
child: Swipe(
onSwipeUp: () {SOMECODE});
}
},
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: GridView.count(
physics: NeverScrollableScrollPhysics(),
crossAxisCount: 11,
children: grid,
),
),
],
),
),
),
);
}
}
CodePudding user response:
I think it would be easier to not cache the containers. Create 121 new ones and mark the ones that are snake parts. You could even do that in "gametick", because it only really changes on "gametick", no point in doing it on every build.
Also, gametick only needs a single setState
, not multiple one's in a loop. You don't want to call your build method multiple times while you are constructing your new game state.
Your gametick method should do all calculations. Then create a new grid (probably it's easier to do it from scratch instead of modifying the old one). And then, it should call setState
once.