mnemo_cards/funny_letters/lib/runner/bonuses/letter_bonus.dart
2025-11-11 02:55:41 +03:00

167 lines
4.3 KiB
Dart

import 'dart:async';
import 'dart:typed_data';
import 'dart:ui';
import 'package:flame/collisions.dart';
import 'package:flame/text.dart';
import 'package:flutter/material.dart';
import 'package:funny_letters/runner/bonuses/bonus.dart';
import 'package:flame/components.dart';
import 'package:flame/flame.dart' as flame;
final _colors = [
const Color(0xffF35050),
const Color(0xffF38335),
const Color(0xffFfc211),
const Color(0xffFFF371),
const Color(0xffD9F17F),
const Color(0xffB2F250),
const Color(0xff55d2b0),
const Color(0xff55d2e9),
const Color(0xff20a0f0),
const Color(0xff8666f9),
const Color(0xffd6a9f8),
const Color(0xffB250F3),
const Color(0xffF250F3),
const Color(0xffF350B2),
const Color(0xffaaaaaa),
const Color(0xff555555),
const Color(0xffeeeeee),
];
class LetterBonus extends PositionComponent with CollisionCallbacks, Bonus {
LetterBonus(Vector2 size, this.letter) {
this.size = size;
this.anchor = Anchor.center;
}
final String letter;
static Future<Uint8List> rasterize(Component component, double width) async {
final recorder = PictureRecorder();
final canvas = Canvas(
recorder,
Rect.fromPoints(
const Offset(0, 0),
Offset(width, width),
),
);
await component.onLoad();
component.render(canvas);
final picture = recorder.endRecording();
final image = await picture.toImage(width.toInt(), width.toInt());
final byteData = await image.toByteData(format: ImageByteFormat.png);
return byteData!.buffer.asUint8List();
}
static Widget image({
required String letter,
required double width,
}) {
return FutureBuilder(
future: rasterize(LetterBonus(Vector2(width, width), letter), width),
builder: (context, snapshot) {
if (snapshot.hasData == false) {
return SizedBox(
width: width,
height: width,
);
}
return Image.memory(
snapshot.requireData,
width: width,
height: width,
);
});
}
@override
FutureOr<void> onLoad() async {
// final engLetter = letter
// .replaceAll('á,', 'a')
// .replaceAll('é', 'e')
// .replaceAll('í', 'i')
// .replaceAll('ó', 'o')
// .replaceAll('ú', 'u')
// .replaceAll('ü', 'u')
// .replaceAll('ñ', 'n');
// sprite = await letterSprite(engLetter);
addAll(
[
RoundedComponent(
size: size,
color: _colors[letter.codeUnitAt(0) % _colors.length],
cornerRadius: size.x / 6,
shadow: true,
),
TextComponent(
text: letter.toUpperCase(),
textRenderer: TextPaint(
style: TextStyle(
fontWeight: FontWeight.w900,
fontFamily: 'Nunito',
fontSize: size.y * 0.9,
textBaseline: TextBaseline.alphabetic,
color: const Color(0xff000000),
),
),
anchor: Anchor.center,
position: size * 0.5,
size: size,
),
],
);
add(
RectangleHitbox(
size: this.size * 0.9, position: size / 2, anchor: Anchor.center),
);
}
}
class RoundedComponent extends PositionComponent {
final Color color;
final double cornerRadius;
final bool shadow;
RoundedComponent({
required super.size,
this.color = const Color(0xFFFFFFFF),
this.cornerRadius = 50,
this.shadow = false,
super.position,
});
@override
void render(Canvas canvas) {
if (shadow) {
canvas.drawRRect(
RRect.fromRectAndRadius(
Rect.fromLTWH(0, height / 10, width, height),
Radius.circular(cornerRadius),
),
Paint()
..color = const Color(0x44000000)
..style = PaintingStyle.fill,
);
}
canvas.drawRRect(
RRect.fromRectAndRadius(
Rect.fromLTWH(0, 0, width, height),
Radius.circular(cornerRadius),
),
Paint()
..color = color
..style = PaintingStyle.fill,
);
canvas.drawRRect(
RRect.fromRectAndRadius(
Rect.fromLTWH(0, 0, width, height),
Radius.circular(cornerRadius),
),
Paint()
..color = const Color(0xFFdddddd)
..style = PaintingStyle.stroke,
);
}
}